int eventLoop() { register int ret; // register int sigEvent; while( true ) { ret = HttpGlobals::getMultiplexer()->waitAndProcessEvents( 1000 ); if (( ret == -1 )&& errno ) { if (!((errno == EINTR )||(errno == EAGAIN))) { fprintf( stderr, "Unexpected error inside event loop: %s", strerror( errno ) ); return 1; } } //printf( ".\n" ); processTimer(); /* if ( (sigEvent = HttpSignals::gotEvent()) ) { HttpSignals::resetEvents(); if ( sigEvent & HS_USR2 ) { HttpLog::toggleDebugLog(); } if ( sigEvent & HS_CHILD ) { HttpServer::cleanPid(); } if ( sigEvent & HS_STOP ) break; } */ /* onIdleTime(); */ LsLuaEngine::testCmd(); /* static int first = 1; if (first) { LsLuaEngine::testCmd(); first = 0; } */ } return 0; }
void MachServer::runServerThread(bool doTimeout) { // allocate request/reply buffers Message bufRequest(mMaxSize); Message bufReply(mMaxSize); // all exits from runServerThread are through exceptions try { // register as a worker thread perThread().server = this; for (;;) { // progress hook eventDone(); // process all pending timers while (processTimer()) {} // check for worker idle timeout { StLock<Mutex> _(managerLock); // record idle thread low-water mark in scan interval if (idleCount < leastIdleWorkers) leastIdleWorkers = idleCount; // perform self-timeout processing if (doTimeout) { if (workerCount > maxWorkerCount) // someone reduced maxWorkerCount recently... break; // ... so release this thread immediately Time::Absolute rightNow = Time::now(); if (rightNow >= nextCheckTime) { // reaping period complete; process UInt32 idlers = leastIdleWorkers; secinfo("machserver", "reaping workers: %d %d", (uint32_t) workerCount, (uint32_t) idlers); nextCheckTime = rightNow + workerTimeout; leastIdleWorkers = INT_MAX; if (idlers > 1) // multiple idle threads throughout measuring interval... break; // ... so release this thread now } } } // determine next timeout (if any) bool indefinite = false; Time::Interval timeout = workerTimeout; { StLock<Mutex> _(managerLock); if (timers.empty()) { indefinite = !doTimeout; } else { timeout = max(Time::Interval(0), timers.next() - Time::now()); if (doTimeout && workerTimeout < timeout) timeout = workerTimeout; } } // receive next IPC request (or wait for timeout) mach_msg_return_t mr = indefinite ? mach_msg_overwrite(bufRequest, MACH_RCV_MSG | mMsgOptions, 0, mMaxSize, mPortSet, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL, (mach_msg_header_t *) 0, 0) : mach_msg_overwrite(bufRequest, MACH_RCV_MSG | MACH_RCV_TIMEOUT | MACH_RCV_INTERRUPT | mMsgOptions, 0, mMaxSize, mPortSet, mach_msg_timeout_t(timeout.mSeconds()), MACH_PORT_NULL, (mach_msg_header_t *) 0, 0); switch (mr) { case MACH_MSG_SUCCESS: // process received request message below break; default: secinfo("machserver", "received error: %d", mr); continue; } // process received message if (bufRequest.msgId() >= MACH_NOTIFY_FIRST && bufRequest.msgId() <= MACH_NOTIFY_LAST) { // mach kernel notification message // we assume this is quick, so no thread arbitration here cdsa_notify_server(bufRequest, bufReply); } else { // normal request message StLock<MachServer, &MachServer::busy, &MachServer::idle> _(*this); secinfo("machserver", "begin request: %d, %d", bufRequest.localPort().port(), bufRequest.msgId()); // try subsidiary handlers first bool handled = false; for (HandlerSet::const_iterator it = mHandlers.begin(); it != mHandlers.end(); it++) if (bufRequest.localPort() == (*it)->port()) { (*it)->handle(bufRequest, bufReply); handled = true; } if (!handled) { // unclaimed, send to main handler handle(bufRequest, bufReply); } secinfo("machserver", "end request"); } // process reply generated by handler if (!(bufReply.bits() & MACH_MSGH_BITS_COMPLEX) && bufReply.returnCode() != KERN_SUCCESS) { if (bufReply.returnCode() == MIG_NO_REPLY) continue; // don't destroy the reply port right, so we can send an error message bufRequest.remotePort(MACH_PORT_NULL); mach_msg_destroy(bufRequest); } if (bufReply.remotePort() == MACH_PORT_NULL) { // no reply port, so destroy the reply if (bufReply.bits() & MACH_MSGH_BITS_COMPLEX) bufReply.destroy(); continue; } /* * We don't want to block indefinitely because the client * isn't receiving messages from the reply port. * If we have a send-once right for the reply port, then * this isn't a concern because the send won't block. * If we have a send right, we need to use MACH_SEND_TIMEOUT. * To avoid falling off the kernel's fast RPC path unnecessarily, * we only supply MACH_SEND_TIMEOUT when absolutely necessary. */ mr = mach_msg_overwrite(bufReply, (MACH_MSGH_BITS_REMOTE(bufReply.bits()) == MACH_MSG_TYPE_MOVE_SEND_ONCE) ? MACH_SEND_MSG | mMsgOptions : MACH_SEND_MSG | MACH_SEND_TIMEOUT | mMsgOptions, bufReply.length(), 0, MACH_PORT_NULL, 0, MACH_PORT_NULL, NULL, 0); switch (mr) { case MACH_MSG_SUCCESS: break; default: secinfo("machserver", "send error: %d %d", mr, bufReply.remotePort().port()); bufReply.destroy(); break; } // clean up after the transaction releaseDeferredAllocations(); } perThread().server = NULL; } catch (...) { perThread().server = NULL; throw; } }
void Timeline::waitForCompletion() { while(_isRunning) processTimer(); }