Example #1
0
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();
    }