示例#1
0
/*
    Invoke the next signal handler. Runs from the dispatcher so signal handlers don't have to be async-safe.
 */
static void signalEvent(MprSignal *sp, MprEvent *event)
{
    MprSignal   *np;
    
    mprAssert(sp);
    mprAssert(event);

    mprLog(7, "signalEvent signo %d, flags %x", sp->signo, sp->flags);
    np = sp->next;

    if (sp->flags & MPR_SIGNAL_BEFORE) {
        (sp->handler)(sp->data, sp);
    } 
    if (sp->sigaction) {
        /*
            Call the original (foreign) action handler. Can't pass on siginfo, because there is no reliable and scalable
            way to save siginfo state when the signalHandler is reentrant for a given signal across multiple threads.
         */
        (sp->sigaction)(sp->signo, NULL, NULL);
    }
    if (sp->flags & MPR_SIGNAL_AFTER) {
        (sp->handler)(sp->data, sp);
    }
    if (np) {
        /* 
            Call all chained signal handlers. Create new event for each handler so we get the right dispatcher.
            WARNING: sp may have been removed and so sp->next may be null. That is why we capture np = sp->next above.
         */
        mprCreateEvent(np->dispatcher, "signalEvent", 0, signalEvent, np, 0);
    }
}
示例#2
0
/*
    function passRequest(req: Request, worker: Worker): Void
 */
static EjsVoid *hs_passRequest(Ejs *ejs, EjsHttpServer *server, int argc, EjsAny **argv)
{
    Ejs             *nejs;
    EjsRequest      *req, *nreq;
    EjsWorker       *worker;
    HttpConn        *conn;
    MprEvent        *event;

    req = argv[0];
    worker = argv[1];

    nejs = worker->pair->ejs;
    conn = req->conn;
    conn->ejs = nejs;

    if ((nreq = ejsCloneRequest(nejs, req, 1)) == 0) {
        ejsThrowStateError(ejs, "Cannot clone request");
        return 0;
    }
    httpSetConnContext(conn, nreq);

    if ((nreq->server = ejsCloneHttpServer(nejs, req->server, 1)) == 0) {
        ejsThrowStateError(ejs, "Cannot clone request");
        return 0;
    }
    event = mprCreateEvent(conn->dispatcher, "RequestWorker", 0, receiveRequest, nreq, MPR_EVENT_DONT_QUEUE);
    httpUseWorker(conn, nejs->dispatcher, event);
    return 0;
}
示例#3
0
PUBLIC int mprCreateEventOutside(MprDispatcher *dispatcher, cchar *name, void *proc, void *data, int flags)
{
    if (mprCreateEvent(dispatcher, name, 0, proc, data, flags) == 0) {
        return MPR_ERR_CANT_CREATE;
    }
    return 0;
}
示例#4
0
/*
    Post a message to this worker. Note: the worker is the destination worker which may be the parent.

    function postMessage(data: Object, ports: Array = null): Void
 */
static EjsObj *workerPostMessage(Ejs *ejs, EjsWorker *worker, int argc, EjsObj **argv)
{
    EjsString       *data;
    EjsWorker       *target;
    MprDispatcher   *dispatcher;
    Message         *msg;

    if (worker->state >= EJS_WORKER_CLOSED) {
        ejsThrowStateError(ejs, "Worker has completed");
        return 0;
    }
    /*
        Create the event with serialized data in the originating interpreter. It owns the data.
     */
    ejsBlockGC(ejs);
    if ((data = ejsToJSON(ejs, argv[0], NULL)) == 0) {
        ejsThrowArgError(ejs, "Cannot serialize message data");
        return 0;
    }
    if ((msg = createMessage()) == 0) {
        ejsThrowMemoryError(ejs);
        return 0;
    }
    target = worker->pair;
    msg->data = ejsToMulti(ejs, data);
    msg->worker = target;
    msg->callback = "onmessage";
    msg->callbackSlot = ES_Worker_onmessage;

    dispatcher = target->ejs->dispatcher;
    mprCreateEvent(dispatcher, "postMessage", 0, doMessage, msg, 0);
    return 0;
}
示例#5
0
/*
 *  Post a message to this worker. Note: the worker is the destination worker which may be the parent.
 *
 *  function postMessage(data: Object, ports: Array = null): Void
 */
static EjsVar *workerPostMessage(Ejs *ejs, EjsWorker *worker, int argc, EjsVar **argv)
{
    EjsVar          *data;
    EjsWorker       *target;
    MprDispatcher   *dispatcher;
    Message         *msg;

    if (worker->state >= EJS_WORKER_CLOSED) {
        ejsThrowStateError(ejs, "Worker has completed");
        return 0;
    }

    /*
     *  Create the event with serialized data in the originating interpreter. It owns the data.
     */
    if ((data = ejsSerialize(ejs, argv[0], -1, 0, 0)) == 0) {
        ejsThrowArgError(ejs, "Can't serialize message data");
        return 0;
    }
    if ((msg = mprAllocObjZeroed(ejs, Message)) == 0) {
        ejsThrowMemoryError(ejs);
        return 0;
    }
    target = worker->pair;
    msg->data = mprStrdup(target->ejs, ejsGetString(data));
    msg->worker = target;
    msg->callback = "onmessage";
    msg->callbackSlot = ES_ejs_sys_Worker_onmessage;

    dispatcher = target->ejs->dispatcher;
    mprCreateEvent(dispatcher, (MprEventProc) doMessage, 0, MPR_NORMAL_PRIORITY, msg, 0);
    mprSignalCond(dispatcher->cond);
    return 0;
}
示例#6
0
/*
    Read the output data from the CGI script and return it to the client. This is called by the MPR in response to
    I/O events from the CGI process for stdout/stderr data from the CGI script and for EOF from the CGI's stdin.
    IMPORTANT: This event runs on the connection's dispatcher. (ie. single threaded and safe)
 */
static void cgiCallback(MprCmd *cmd, int channel, void *data)
{
    HttpConn    *conn;
    Cgi         *cgi;
    int         suspended;

    if ((cgi = data) == 0) {
        return;
    }
    if ((conn = cgi->conn) == 0) {
        return;
    }
    conn->lastActivity = conn->http->now;

    switch (channel) {
    case MPR_CMD_STDIN:
        /* Stdin can absorb more data */
        httpResumeQueue(cgi->writeq);
        break;

    case MPR_CMD_STDOUT:
    case MPR_CMD_STDERR:
        readFromCgi(cgi, channel);
        break;
            
    default:
        /* Child death notification */
        if (cmd->status != 0) {
            httpError(cgi->conn, HTTP_CODE_BAD_GATEWAY, "Bad CGI process termination");
        }
        break;
    }
    if (cgi->location) {
        httpRedirect(conn, conn->tx->status, cgi->location);
    }
    if (cmd->complete || cgi->location) {
        cgi->location = 0;
        httpFinalize(conn);
        mprCreateEvent(conn->dispatcher, "cgiComplete", 0, httpIOEvent, conn, 0);
        return;
    } 
    suspended = httpIsQueueSuspended(conn->writeq);
    assert(!suspended || conn->tx->writeBlocked);
    mprEnableCmdOutputEvents(cmd, !suspended);
    mprCreateEvent(conn->dispatcher, "cgi", 0, httpIOEvent, conn, 0);
}
示例#7
0
/*
    Read the output data from the CGI script and return it to the client. This is called by the MPR in response to
    I/O events from the CGI process for stdout/stderr data from the CGI script and for EOF from the CGI's stdin.
    IMPORTANT: This event runs on the connection's dispatcher. (ie. single threaded and safe)
 */
static void cgiCallback(MprCmd *cmd, int channel, void *data)
{
    HttpConn    *conn;
    Cgi         *cgi;
    int         suspended;

    if ((cgi = data) == 0) {
        return;
    }
    if ((conn = cgi->conn) == 0) {
        return;
    }
    conn->lastActivity = conn->http->now;
    mprTrace(6, "CGI: cgiCallback event channel %d", channel);

    switch (channel) {
    case MPR_CMD_STDIN:
        /* Stdin can absorb more data */
        httpResumeQueue(cgi->writeq);
        break;

    case MPR_CMD_STDOUT:
    case MPR_CMD_STDERR:
        readFromCgi(cgi, channel);
        break;
            
    default:
        /* Child death notification */
        break;
    }
    if (cgi->location) {
        httpRedirect(conn, conn->tx->status, cgi->location);
    }
    if (cmd->complete || cgi->location) {
        cgi->location = 0;
        httpFinalize(conn);
        mprCreateEvent(conn->dispatcher, "cgiComplete", 0, httpIOEvent, conn, 0);
        return;
    } 
    suspended = httpIsQueueSuspended(conn->writeq);
    mprTrace(6, "CGI: %s CGI: cgiCallback. Conn->writeq %d", suspended ? "DISABLE" : "ENABLE", conn->writeq->count);
    assert(!suspended || conn->tx->writeBlocked);
    mprEnableCmdOutputEvents(cmd, !suspended);
    mprCreateEvent(conn->dispatcher, "cgi", 0, httpIOEvent, conn, 0);
}
示例#8
0
文件: conn.c 项目: DavidQuan/http
PUBLIC void httpScheduleConnTimeout(HttpConn *conn)
{
    if (!conn->timeoutEvent && !conn->destroyed) {
        /*
            Will run on the HttpConn dispatcher unless shutting down and it is destroyed already
         */
        conn->timeoutEvent = mprCreateEvent(conn->dispatcher, "connTimeout", 0, connTimeout, conn, 0);
    }
}
示例#9
0
/*
    Worker thread main procedure. Worker is the inside worker.
 */
static int workerMain(EjsWorker *insideWorker, MprEvent *event)
{
    Ejs             *outside, *inside;
    EjsWorker       *outsideWorker;
    MprDispatcher   *dispatcher;
    Message         *msg;

    assert(insideWorker->inside);
    outsideWorker = insideWorker->pair;
    assert(!outsideWorker->inside);
    assert(insideWorker->state == EJS_WORKER_BEGIN);

    outside = outsideWorker->ejs;
    inside = insideWorker->ejs;
    insideWorker->state = EJS_WORKER_STARTED;
    
    /*
        Run the script or file
     */
    if (outsideWorker->scriptFile) {
        loadFile(insideWorker, outsideWorker->scriptFile);

    } else if (outsideWorker->scriptLiteral) {
        if (outside->service->loadScriptLiteral == 0) {
            ejsThrowIOError(outside, "worker: Compiling is not enabled");
            return 0;
        }
        (outside->service->loadScriptLiteral)(inside, outsideWorker->scriptLiteral, NULL);
    }
    /*
        Check for exceptions
     */
    if (inside->exception) {
        handleError(outside, outsideWorker, inside->exception, 0);
        inside->exception = 0;
    }
    ejsBlockGC(inside);
    if ((msg = createMessage()) == 0) {
        ejsThrowMemoryError(outside);
        return 0;
    }
    /*
        Post "onclose" finalization message
     */
    msg->worker = outsideWorker;
    msg->callback = "onclose";
    msg->callbackSlot = ES_Worker_onclose;

    insideWorker->state = EJS_WORKER_CLOSED;
    outsideWorker->state = EJS_WORKER_CLOSED;
    dispatcher = outside->dispatcher;
    mprCreateEvent(dispatcher, "doMessage", 0, (MprEventProc) doMessage, msg, 0);
    return 0;
}
示例#10
0
/*
 *  Worker thread main procedure
 */
static void workerMain(EjsWorker *worker, MprWorker *mprWorker)
{
    Ejs             *ejs, *inside;
    EjsWorker       *insideWorker;
    MprDispatcher   *dispatcher;
    Message         *msg;

    mprAssert(!worker->inside);
    insideWorker = worker->pair;
    mprAssert(insideWorker->state == EJS_WORKER_BEGIN);

    ejs = worker->ejs;
    inside = insideWorker->ejs;
    insideWorker->state = EJS_WORKER_STARTED;
    
    /*
     *  Run the script or file
     */
    if (worker->scriptFile) {
        loadFile(insideWorker, worker->scriptFile);

    } else if (worker->scriptLiteral) {
        if (ejs->service->loadScriptLiteral == 0) {
            ejsThrowIOError(ejs, "worker: Compiling is not enabled");
            return;
        }
        (ejs->service->loadScriptLiteral)(inside, worker->scriptLiteral);
    }

    /*
     *  Check for exceptions
     */
    if (inside->exception) {
        handleError(ejs, worker, inside->exception);
    }
    if ((msg = mprAllocObjZeroed(ejs, Message)) == 0) {
        ejsThrowMemoryError(ejs);
        return;
    }

    /*
     *  Post "onclose" finalization message
     */
    msg->worker = worker;
    msg->callback = "onclose";
    msg->callbackSlot = ES_ejs_sys_Worker_onclose;

    insideWorker->state = EJS_WORKER_CLOSED;
    worker->state = EJS_WORKER_CLOSED;
    insideWorker->obj.var.permanent = 0;
    dispatcher = worker->ejs->dispatcher;
    mprCreateEvent(dispatcher, (MprEventProc) doMessage, 0, MPR_NORMAL_PRIORITY, msg, 0);
    mprSignalCond(dispatcher->cond);
}
示例#11
0
/*
    WARNING: the inside interpreter owns the exception object. Must fully extract all fields
 */
static void handleError(Ejs *ejs, EjsWorker *worker, EjsObj *exception, int throwOutside)
{
    Ejs             *inside;
    EjsObj          *e;
    MprDispatcher   *dispatcher;
    Message         *msg;

    assert(!worker->inside);
    assert(exception);
    assert(ejs == worker->ejs);

    ejsBlockGC(ejs);
    if ((msg = createMessage()) == 0) {
        ejsThrowMemoryError(ejs);
        return;
    }
    msg->worker = worker;
    msg->callback = "onerror";
    msg->callbackSlot = ES_Worker_onerror;
    inside = worker->pair->ejs;
    
    inside->exception = 0;
    e = ejsDeserialize(ejs, ejsSerialize(inside, exception, 0));
    inside->exception = exception;

    /*
        Inside interpreter owns the exception object, so must fully extract all exception. 
        Allocate into the outside worker's interpreter.
     */
    if (ejsIsError(inside, exception)) {
        msg->message = ejsGetPropertyByName(ejs, e, EN("message"));
        msg->stack = ejsGetPropertyByName(ejs, e, EN("stack"));
    } else {
        msg->message = e;
        msg->stack = 0;
    }
    if (throwOutside) {
        if (msg->stack) {
            ejsThrowStateError(ejs, "%@\n%@", ejsToString(ejs, msg->message), ejsToString(ejs, msg->stack));
        } else {
            ejsThrowStateError(ejs, "%@", ejsToString(ejs, msg->message));
        }
    }
    dispatcher = ejs->dispatcher;
    mprCreateEvent(dispatcher, "doMessage-error", 0, (MprEventProc) doMessage, msg, 0);
}
示例#12
0
/*
    Start a worker thread. This is called by eval() and load(). Not by preload() or by Worker(). It always joins.
 */
static EjsObj *startWorker(Ejs *ejs, EjsWorker *outsideWorker, int timeout)
{
    EjsWorker   *insideWorker;
    Ejs         *inside;
    EjsString   *result;

    assert(ejs);
    assert(outsideWorker);
    assert(!outsideWorker->inside);
    assert(outsideWorker->state == EJS_WORKER_BEGIN);
    assert(outsideWorker->pair);
    assert(outsideWorker->pair->ejs);

    mprTrace(5, "Worker.startWorker");

    if (outsideWorker->state > EJS_WORKER_BEGIN) {
        ejsThrowStateError(ejs, "Worker has already started");
        return 0;
    }
    insideWorker = outsideWorker->pair;
    assert(insideWorker->inside);
    assert(insideWorker->state == EJS_WORKER_BEGIN);
    inside = insideWorker->ejs;

    outsideWorker->state = EJS_WORKER_STARTED;

    if (mprCreateEvent(inside->dispatcher, "workerMain", 0, (MprEventProc) workerMain, insideWorker, 0) < 0) {
        ejsThrowStateError(ejs, "Cannot create worker event");
        return 0;
    }
    if (timeout == 0) {
        return ESV(undefined);
    } 
    if (timeout < 0) {
        timeout = MAXINT;
    }
    if (join(ejs, (EjsObj*) outsideWorker, timeout) < 0) {
        return ESV(undefined);
    }
    result = ejsToJSON(inside, inside->result, NULL);
    if (result == 0) {
        return ESV(null);
    }
    return ejsDeserialize(ejs, result);
}
示例#13
0
文件: wait.c 项目: embedthis/mpr
PUBLIC void mprQueueIOEvent(MprWaitHandler *wp)
{
    MprDispatcher   *dispatcher;
    MprEvent        *event;

    if (wp->flags & MPR_WAIT_NEW_DISPATCHER) {
        dispatcher = mprCreateDispatcher("IO", MPR_DISPATCHER_AUTO);
    } else if (wp->dispatcher) {
        dispatcher = wp->dispatcher;
    } else {
        dispatcher = mprGetDispatcher();
    }
    event = mprCreateEvent(dispatcher, "IOEvent", 0, ioEvent, wp->handlerData, MPR_EVENT_DONT_QUEUE);
    event->mask = wp->presentMask;
    event->handler = wp;
    wp->event = event;
    mprQueueEvent(dispatcher, event);
}
示例#14
0
/*
    Event callback. Invoked for incoming web socket messages and other events of interest.
 */
static void chat_callback(HttpConn *conn, int event, int arg)
{
    HttpPacket  *packet;
    HttpConn    *client;
    Msg         *msg;
    int         next;

    if (event == HTTP_EVENT_READABLE) {
        packet = httpGetPacket(conn->readq);
        if (packet->type == WS_MSG_TEXT || packet->type == WS_MSG_BINARY) {
            for (ITERATE_ITEMS(clients, client, next)) {
                msg = mprAllocObj(Msg, manageMsg);
                msg->conn = client;
                msg->packet = packet;
                mprCreateEvent(client->dispatcher, "chat", 0, chat, msg, 0);
            }
        }
    } else if (event == HTTP_EVENT_APP_CLOSE) {
示例#15
0
static void testCriticalSection(MprTestGroup *gp)
{
    MprCond     *cond;
    MprEvent    *event;
    int         rc;

    cond = mprCreateCond(gp);
    assert(cond != 0);
    mprAssert(cond->triggered == 0);

    /*
     *  Create an event to signal the condition var in 10 msec
     */
    event = mprCreateEvent(mprGetDispatcher(gp), callback, 0, 0, (void*) cond, 0);
    assert(event != 0);
    rc = mprWaitForCondWithService(cond, MPR_TEST_TIMEOUT);
    assert(rc == 0);
    mprFree(cond);
    mprFree(event);
}
示例#16
0
/*
 *  WARNING: the inside interpreter owns the exception object. Must fully extract all fields
 */
static void handleError(Ejs *ejs, EjsWorker *worker, EjsVar *exception)
{
    EjsError        *error;
    MprDispatcher   *dispatcher;
    Message         *msg;

    mprAssert(!worker->inside);
    mprAssert(exception);
    mprAssert(ejs == worker->ejs);

    if ((msg = mprAllocObjZeroed(ejs, Message)) == 0) {
        ejsThrowMemoryError(ejs);
        return;
    }
    msg->worker = worker;
    msg->callback = "onerror";
    msg->callbackSlot = ES_ejs_sys_Worker_onerror;
    
    /*
     *  Inside interpreter owns the exception object, so must fully extract all exception. 
     *  Allocate into the outside worker's interpreter.
     */
    if (ejsIsError(exception)) {
        error = (EjsError*) exception;
        msg->message = mprStrdup(ejs, error->message);
        msg->filename = mprStrdup(ejs, error->filename ? error->filename : "script");
        msg->lineNumber = error->lineNumber;
        msg->stack = mprStrdup(ejs, error->stack);

    } else if (ejsIsString(exception)) {
        msg->message = mprStrdup(ejs, ejsGetString(exception));

    } else {
        msg->message = mprStrdup(ejs, ejsGetString(ejsToString(ejs, exception)));
    }
    dispatcher = ejs->dispatcher;
    mprCreateEvent(dispatcher, (MprEventProc) doMessage, 0, MPR_NORMAL_PRIORITY, msg, 0);
    mprSignalCond(dispatcher->cond);
}
示例#17
0
/*
    Called by mprServiceEvents after a signal has been received. Create an event and queue on the appropriate dispatcher
 */
void mprServiceSignals()
{
    MprSignalService    *ssp;
    MprSignal           *sp;
    MprSignalInfo       *ip;
    int                 signo;

    ssp = MPR->signalService;
    ssp->hasSignals = 0;
    for (ip = ssp->info; ip < &ssp->info[MPR_MAX_SIGNALS]; ip++) {
        if (ip->triggered) {
            ip->triggered = 0;
            /*
                Create an event for the head of the signal handler chain for this signal
                Copy info from Thread.sigInfo to MprSignal structure.
             */
            signo = (int) (ip - ssp->info);
            if ((sp = ssp->signals[signo]) != 0) {
                mprCreateEvent(sp->dispatcher, "signalEvent", 0, signalEvent, sp, 0);
            }
        }
    }
}
示例#18
0
/*
    Do a performance benchmark
 */ 
static void doBenchmark(void *thread)
{
    MprTime         start;
    MprList         *list;
    int             count, i;
    MprMutex        *lock;
    MprSpin         *spin;

    mprPrintf("Group\t%-30s\t%13s\t%12s\n", "Benchmark", "Microsec", "Elapsed-sec");

    testMalloc();

    if (!app->testAllocOnly) {
        /*
            Locking primitives
         */
        mprPrintf("Lock Benchmarks\n");
        lock = mprCreateLock();
        count = 5000000 * app->iterations;
        start = startMark();
        for (i = 0; i < count; i++) {
            mprLock(lock);
            mprUnlock(lock);
        }
        endMark(start, count, "Mutex lock|unlock");
        
        /*
            Locking primitives
         */
        mprPrintf("Lock Benchmarks\n");
        spin = mprCreateSpinLock();
        count = 5000000 * app->iterations;
        start = startMark();
        for (i = 0; i < count; i++) {
            mprSpinLock(spin);
            mprSpinUnlock(spin);
        }
        endMark(start, count, "Spin lock|unlock");
        
        /*
            Condition signal / wait
         */
        mprPrintf("Cond Benchmarks\n");
        count = 1000000 * app->iterations;
        start = startMark();
        mprResetCond(app->complete);
        for (i = 0; i < count; i++) {
            mprSignalCond(app->complete);
            mprWaitForCond(app->complete, -1);
        }
        endMark(start, count, "Cond signal|wait");
        
        /*
            List
         */
        mprPrintf("List Benchmarks\n");
        count = 2000000 * app->iterations;
        list = mprCreateList(count, 0);
        start = startMark();
        for (i = 0; i < count; i++) {
            mprAddItem(list, (void*) (long) i);
            mprRemoveItem(list, (void*) (long) i);
        }
        endMark(start, count, "Link insert|remove");

        /*
            Events
         */
        mprPrintf("Event Benchmarks\n");
        mprResetCond(app->complete);
        count = 30000 * app->iterations;
        app->markCount = count;
        start = startMark();
        for (i = 0; i < count; i++) {
            mprCreateEvent(NULL, "eventBenchmark", 0, eventCallback, ITOP(i), MPR_EVENT_QUICK);
        }
        mprWaitForCond(app->complete, -1);
        endMark(start, count, "Event (create|run|delete)");

        /*
            Test timer creation, run and remove
            These create a new dispatcher and run a worker thread.
         */
        mprPrintf("Timer\n");
        mprResetCond(app->complete);
        count = 20000 * app->iterations;
        app->markCount = count;
        start = startMark();
        for (i = 0; i < count; i++) {
            mprCreateTimerEvent(NULL, "timerBenchmark", 0, timerCallback, (void*) (long) i, 0);
        }
        mprWaitForCond(app->complete, -1);
        endMark(start, count, "Timer (create|delete)");

        /*
            Alloc (1K)
         */
        mprPrintf("Alloc 1K Benchmarks\n");
        count = 2000000 * app->iterations;
        start = startMark();
        for (i = 0; i < count; i++) {
            mprAlloc(1024);
            if ((i % 128) == 0) {
                mprGC(0);
            }
        }
        endMark(start, count, "Alloc mprAlloc(1K)");
    }
    testComplete = 1;
}
示例#19
0
static EjsWorker *initWorker(Ejs *ejs, EjsWorker *worker, Ejs *baseVM, cchar *name, EjsArray *search, cchar *scriptFile)
{
    Ejs             *wejs;
    EjsWorker       *self;
    EjsName         sname;
    static int      workerSeqno = 0;

    ejsBlockGC(ejs);
    if (worker == 0) {
        worker = ejsCreateWorker(ejs);
    }
    worker->ejs = ejs;
    worker->state = EJS_WORKER_BEGIN;

    if (name) {
        worker->name = sclone(name);
    } else {
        lock(ejs);
        worker->name = sfmt("worker-%d", workerSeqno++);
        unlock(ejs);
    }
    /*
        Create a new interpreter and an "inside" worker object and pair it with the current "outside" worker.
        The worker interpreter gets a new dispatcher
     */
    if (baseVM) {
        if ((wejs = ejsCloneVM(baseVM)) == 0) {
            ejsThrowMemoryError(ejs);
            return 0;
        }
    } else {
        if ((wejs = ejsCreateVM(0, 0, ejs->flags)) == 0) {
            ejsThrowMemoryError(ejs);
            return 0;
        }
        if (ejsLoadModules(wejs, 0, 0) < 0) {
            return 0;
        }
    }
    worker->pair = self = ejsCreateWorker(wejs);
    self->state = EJS_WORKER_BEGIN;
    self->ejs = wejs;
    self->inside = 1;
    self->pair = worker;
    self->name = sjoin("inside-", worker->name, NULL);
#if MOB
    mprEnableDispatcher(wejs->dispatcher);
#endif
    if (search) {
        ejsSetSearchPath(ejs, (EjsArray*) search);
    }

    //  TODO - these should be don't delete
    ejsSetProperty(ejs, worker, ES_Worker_name, ejsCreateStringFromAsc(ejs, self->name));
    ejsSetProperty(wejs, self,  ES_Worker_name, ejsCreateStringFromAsc(wejs, self->name));

    sname = ejsName(wejs, EJS_WORKER_NAMESPACE, "self");
    ejsSetPropertyByName(wejs, wejs->global, sname, self);

    /*
        Workers have a dedicated namespace to enable viewing of the worker globals (self, onmessage, postMessage...)
     */
    ejsDefineReservedNamespace(wejs, wejs->global, NULL, EJS_WORKER_NAMESPACE);
    
    addWorker(ejs, worker);

    if (scriptFile) {
        worker->scriptFile = sclone(scriptFile);
        worker->state = EJS_WORKER_STARTED;
        if (mprCreateEvent(wejs->dispatcher, "workerMain", 0, (MprEventProc) workerMain, self, 0) < 0) {
            mprRemoveItem(ejs->workers, worker);
            ejsThrowStateError(ejs, "Cannot create worker event");
            return 0;
        }
    }
    return worker;
}
示例#20
0
文件: espAbbrev.c 项目: embedthis/esp
PUBLIC void setTimeout(void *proc, MprTicks timeout, void *data)
{
    mprCreateEvent(getStream()->dispatcher, "setTimeout", (int) timeout, proc, data, 0);
}
示例#21
0
/*
    Create an interval timer
 */
PUBLIC MprEvent *mprCreateTimerEvent(MprDispatcher *dispatcher, cchar *name, MprTicks period, void *proc,
    void *data, int flags)
{
    return mprCreateEvent(dispatcher, name, period, proc, data, MPR_EVENT_CONTINUOUS | flags);
}
示例#22
0
/*  
    Start the CGI command program. This commences the CGI gateway program. This will be called after content for
    form and upload requests (or if "RunHandler" before specified), otherwise it runs before receiving content data.
 */
static void startCgi(HttpQueue *q)
{
    HttpRx          *rx;
    HttpTx          *tx;
    HttpRoute       *route;
    HttpConn        *conn;
    MprCmd          *cmd;
    Cgi             *cgi;
    cchar           *baseName, **argv, *fileName, **envv;
    ssize           varCount;
    int             argc, count;

    argv = 0;
    argc = 0;
    cgi = q->queueData;
    conn = q->conn;
    rx = conn->rx;
    route = rx->route;
    tx = conn->tx;

    /*
        The command uses the conn dispatcher. This serializes all I/O for both the connection and the CGI gateway.
     */
    if ((cmd = mprCreateCmd(conn->dispatcher)) == 0) {
        return;
    }
    cgi->cmd = cmd;

    if (conn->http->forkCallback) {
        cmd->forkCallback = conn->http->forkCallback;
        cmd->forkData = conn->http->forkData;
    }
    argc = 1;                                   /* argv[0] == programName */
    buildArgs(conn, cmd, &argc, &argv);
    fileName = argv[0];
    baseName = mprGetPathBase(fileName);
    
    /*
        nph prefix means non-parsed-header. Don't parse the CGI output for a CGI header
     */
    if (strncmp(baseName, "nph-", 4) == 0 || 
            (strlen(baseName) > 4 && strcmp(&baseName[strlen(baseName) - 4], "-nph") == 0)) {
        /* Pretend we've seen the header for Non-parsed Header CGI programs */
        cgi->seenHeader = 1;
        tx->flags |= HTTP_TX_USE_OWN_HEADERS;
    }
    /*  
        Build environment variables
     */
    varCount = mprGetHashLength(rx->headers) + mprGetHashLength(rx->svars) + mprGetJsonLength(rx->params);
    if ((envv = mprAlloc((varCount + 1) * sizeof(char*))) != 0) {
        count = copyParams(conn, envv, 0, rx->params, route->envPrefix);
        count = copyVars(conn, envv, count, rx->svars, "");
        count = copyVars(conn, envv, count, rx->headers, "HTTP_");
        assert(count <= varCount);
    }
#if !VXWORKS
    /*
        This will be ignored on VxWorks because there is only one global current directory for all tasks
     */
    mprSetCmdDir(cmd, mprGetPathDir(fileName));
#endif
    mprSetCmdCallback(cmd, cgiCallback, cgi);

    if (mprStartCmd(cmd, argc, argv, envv, MPR_CMD_IN | MPR_CMD_OUT | MPR_CMD_ERR) < 0) {
        httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot run CGI process: %s, URI %s", fileName, rx->uri);
        return;
    }
#if ME_WIN_LIKE
    mprCreateEvent(conn->dispatcher, "cgi-win", 10, waitForCgi, cgi, MPR_EVENT_CONTINUOUS);
#endif
}
示例#23
0
/*
 *  Do a performance benchmark
 */ 
static void doBenchmark(Mpr *mpr, void *thread)
{
    MprTime     start;
    MprList     *list;
    void        *mp;
    int         count, i;
#if BLD_FEATURE_MULTITHREAD
    MprMutex    *lock;
#endif

    complete = mprCreateCond(mpr);

    mprPrintf(mpr, "Group\t%-30s\t%13s\t%12s\n", "Benchmark", "Microsec", "Elapsed-sec");

    /*
     *  Alloc (1K)
     */
    mprPrintf(mpr, "Alloc Benchmarks\n");
    count = 2000000 * iterations;
    start = startMark(mpr);
    for (i = 0; i < count; i++) {
        mp = mprAlloc(mpr, 1024);
        memset(mp, 0, 1024);
        mprFree(mp);
    }
    endMark(mpr, start, count, "Alloc mprAlloc(1K)|mprFree");
    start = startMark(mpr);

#if BLD_FEATURE_MULTITHREAD
    /*
     *  Locking primitives
     */
    mprPrintf(mpr, "Lock Benchmarks\n");
    lock = mprCreateLock(mpr);
    count = 5000000 * iterations;
    start = startMark(mpr);
    for (i = 0; i < count; i++) {
        mprLock(lock);
        mprUnlock(lock);
    }
    endMark(mpr, start, count, "Mutex lock|unlock");
    mprFree(lock);

    /*
     *  Condition signal / wait
     */
    mprPrintf(mpr, "Cond Benchmarks\n");
    count = 1000000 * iterations;
    start = startMark(mpr);
    mprResetCond(complete);
    for (i = 0; i < count; i++) {
        mprSignalCond(complete);
        mprWaitForCond(complete, -1);
    }
    endMark(mpr, start, count, "Cond signal|wait");
#endif

    /*
     *  List
     */
    mprPrintf(mpr, "List Benchmarks\n");
    count = 500000 * iterations;
    list = mprCreateList(mpr);
    start = startMark(mpr);
    for (i = 0; i < count; i++) {
        mprAddItem(list, (void*) (long) i);
        mprRemoveItem(list, (void*) (long) i);
    }
    endMark(mpr, start, count, "Link insert|remove");
    mprFree(list);;

    /*
     *  Events
     */
    mprPrintf(mpr, "Event Benchmarks\n");
    mprResetCond(complete);
    count = 200000 * iterations;
    markCount = count;
    start = startMark(mpr);
    for (i = 0; i < count; i++) {
        mprCreateEvent(mprGetDispatcher(mpr), eventCallback, 0, 0, (void*) (long) i, 0);
    }
    endMark(mpr, start, count, "Event (create)");
    mprWaitForCondWithService(complete, -1);
    endMark(mpr, start, count, "Event (run|delete)");


    /*
     *  Test timer creation, run and delete (make a million timers!)
     */
    mprPrintf(mpr, "Timer\n");
    mprResetCond(complete);
    count = 50000 * iterations;
    markCount = count;
    start = startMark(mpr);
    for (i = 0; i < count; i++) {
        mprCreateTimerEvent(mprGetDispatcher(mpr), timerCallback, 0, 0, (void*) (long) i, 0);
    }
    endMark(mpr, start, count, "Timer (create)");
    mprWaitForCondWithService(complete, -1);
    endMark(mpr, start, count, "Timer (delete)");

    testComplete = 1;
}