⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpm_winnt.c

📁 Apache V2.0.15 Alpha For Linuxhttpd-2_0_15-alpha.tar.Z
💻 C
📖 第 1 页 / 共 5 页
字号:
            if (head_listener == NULL)                head_listener = ap_listeners;	    return (lr);	}    }    return NULL;}/*  * get_listeners_from_parent() * The listen sockets are opened in the parent. This function, which runs * exclusively in the child process, receives them from the parent and * makes them availeble in the child. */static int get_listeners_from_parent(server_rec *s){    WSAPROTOCOL_INFO WSAProtocolInfo;    HANDLE pipe;    ap_listen_rec *lr;    DWORD BytesRead;    int num_listeners = 0;    SOCKET nsd;    /* Set up a default listener if necessary */    if (ap_listeners == NULL) {        ap_listen_rec *lr;        lr = apr_palloc(s->process->pool, sizeof(ap_listen_rec));        if (!lr)            return 0;        lr->sd = NULL;        lr->next = ap_listeners;        ap_listeners = lr;    }    /* Open the pipe to the parent process to receive the inherited socket     * data. The sockets have been set to listening in the parent process.     */    pipe = GetStdHandle(STD_INPUT_HANDLE);    for (lr = ap_listeners; lr; lr = lr->next) {        if (!ReadFile(pipe, &WSAProtocolInfo, sizeof(WSAPROTOCOL_INFO),                       &BytesRead, (LPOVERLAPPED) NULL)) {            ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,                         "setup_inherited_listeners: Unable to read socket data from parent");            signal_parent(0);	/* tell parent to die */            exit(1);        }        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, server_conf,                     "Child %d: setup_inherited_listener() read = %d bytes of WSAProtocolInfo.", my_pid);        nsd = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,                        &WSAProtocolInfo, 0, 0);        if (nsd == INVALID_SOCKET) {            ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_netos_error(), server_conf,                         "Child %d: setup_inherited_listeners(), WSASocket failed to open the inherited socket.", my_pid);            signal_parent(0);	/* tell parent to die */            exit(1);        }        apr_os_sock_put(&lr->sd, &nsd, pconf);        num_listeners++;    }    CloseHandle(pipe);    return num_listeners;}/* Windows 9x specific code... * Accept processing for on Windows 95/98 uses a producer/consumer queue  * model. A single thread accepts connections and queues the accepted socket  * to the accept queue for consumption by a pool of worker threads. * * win9x_accept() *    The accept threads runs this function, which accepts connections off  *    the network and calls add_job() to queue jobs to the accept_queue. * add_job()/remove_job() *    Add or remove an accepted socket from the list of sockets  *    connected to clients. allowed_globals.jobmutex protects *    against multiple concurrent access to the linked list of jobs. * win9x_get_connection() *    Calls remove_job() to pull a job from the accept queue. All the worker  *    threads block on remove_job. */typedef struct joblist_s {    struct joblist_s *next;    int sock;} joblist;typedef struct globals_s {    HANDLE jobsemaphore;    joblist *jobhead;    joblist *jobtail;    apr_lock_t *jobmutex;    int jobcount;} globals;globals allowed_globals = {NULL, NULL, NULL, NULL, 0};#define MAX_SELECT_ERRORS 100static void add_job(int sock){    joblist *new_job;    new_job = (joblist *) malloc(sizeof(joblist));    if (new_job == NULL) {	ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,                      "Ouch!  Out of memory in add_job()!");        return;    }    new_job->next = NULL;    new_job->sock = sock;    apr_lock_acquire(allowed_globals.jobmutex);    if (allowed_globals.jobtail != NULL)	allowed_globals.jobtail->next = new_job;    allowed_globals.jobtail = new_job;    if (!allowed_globals.jobhead)	allowed_globals.jobhead = new_job;    allowed_globals.jobcount++;    ReleaseSemaphore(allowed_globals.jobsemaphore, 1, NULL);    apr_lock_release(allowed_globals.jobmutex);}static int remove_job(void){    joblist *job;    int sock;    WaitForSingleObject(allowed_globals.jobsemaphore, INFINITE);    apr_lock_acquire(allowed_globals.jobmutex);    if (shutdown_in_progress && !allowed_globals.jobhead) {        apr_lock_release(allowed_globals.jobmutex);	return (-1);    }    job = allowed_globals.jobhead;    ap_assert(job);    allowed_globals.jobhead = job->next;    if (allowed_globals.jobhead == NULL)	allowed_globals.jobtail = NULL;    apr_lock_release(allowed_globals.jobmutex);    sock = job->sock;    free(job);    return (sock);}static void win9x_accept(void * dummy){    int requests_this_child = 0;    struct timeval tv;    fd_set main_fds;    int wait_time = 1;    int csd;    SOCKET nsd = INVALID_SOCKET;    struct sockaddr_in sa_client;    int count_select_errors = 0;    int rc;    int clen;    ap_listen_rec *lr;    struct fd_set listenfds;    SOCKET listenmaxfd = INVALID_SOCKET;    /* Setup the listeners      * ToDo: Use apr_poll()     */    FD_ZERO(&listenfds);    for (lr = ap_listeners; lr; lr = lr->next) {        if (lr->sd != NULL) {            apr_os_sock_get(&nsd, lr->sd);            FD_SET(nsd, &listenfds);            if (listenmaxfd == INVALID_SOCKET || nsd > listenmaxfd) {                listenmaxfd = nsd;            }        }    }    head_listener = ap_listeners;    while (!shutdown_in_progress) {        if (ap_max_requests_per_child && (requests_this_child > ap_max_requests_per_child)) {            break;	}	tv.tv_sec = wait_time;	tv.tv_usec = 0;	memcpy(&main_fds, &listenfds, sizeof(fd_set));	rc = select(listenmaxfd + 1, &main_fds, NULL, NULL, &tv);        if (rc == 0 || (rc == SOCKET_ERROR && APR_STATUS_IS_EINTR(apr_get_netos_error()))) {            count_select_errors = 0;    /* reset count of errors */                        continue;        }        else if (rc == SOCKET_ERROR) {            /* A "real" error occurred, log it and increment the count of             * select errors. This count is used to ensure we don't go into             * a busy loop of continuous errors.             */            ap_log_error(APLOG_MARK, APLOG_INFO, apr_get_netos_error(), server_conf,                          "select failed with error %d", apr_get_netos_error());            count_select_errors++;            if (count_select_errors > MAX_SELECT_ERRORS) {                shutdown_in_progress = 1;                ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_netos_error(), server_conf,                             "Too many errors in select loop. Child process exiting.");                break;            }	} else {	    ap_listen_rec *lr;	    lr = find_ready_listener(&main_fds);	    if (lr != NULL) {                /* fetch the native socket descriptor */                apr_os_sock_get(&nsd, lr->sd);	    }	}	do {            clen = sizeof(sa_client);            csd = accept(nsd, (struct sockaddr *) &sa_client, &clen);            if (csd == INVALID_SOCKET) {                csd = -1;            }        } while (csd < 0 && APR_STATUS_IS_EINTR(apr_get_netos_error()));	if (csd < 0) {            if (APR_STATUS_IS_ECONNABORTED(apr_get_netos_error())) {		ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_netos_error(), server_conf,			    "accept: (client socket)");            }	}	else {	    add_job(csd);	    requests_this_child++;	}    }    SetEvent(exit_event);}static PCOMP_CONTEXT win9x_get_connection(PCOMP_CONTEXT context){    int len;    if (context == NULL) {        /* allocate the completion context and the transaction pool */        context = apr_pcalloc(pconf, sizeof(COMP_CONTEXT));        if (!context) {            ap_log_error(APLOG_MARK,APLOG_ERR, apr_get_os_error(), server_conf,                         "win9x_get_connection: apr_pcalloc() failed. Process will exit.");            return NULL;        }        apr_pool_create(&context->ptrans, pconf);    }        while (1) {        apr_pool_clear(context->ptrans);                context->accept_socket = remove_job();        if (context->accept_socket == -1) {            return NULL;        }	len = sizeof(struct sockaddr);        context->sa_server = apr_palloc(context->ptrans, len);        if (getsockname(context->accept_socket,                         context->sa_server, &len)== SOCKET_ERROR) {            ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), server_conf,                          "getsockname failed");            continue;        }        len = sizeof(struct sockaddr);        context->sa_client = apr_palloc(context->ptrans, len);        if ((getpeername(context->accept_socket,                         context->sa_client, &len)) == SOCKET_ERROR) {            ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_netos_error(), server_conf,                          "getpeername failed");            memset(&context->sa_client, '\0', sizeof(context->sa_client));        }        /* do we NEED_DUPPED_CSD ?? */                return context;    }}/* Windows NT/2000 specific code... * Accept processing for on Windows NT uses a producer/consumer queue  * model. An accept thread accepts connections off the network then issues * PostQueuedCompletionStatus() to awake a thread blocked on the ThreadDispatch  * IOCompletionPort. * * winnt_accept() *    One or more accept threads run in this function, each of which accepts  *    connections off the network and calls PostQueuedCompletionStatus() to *    queue an io completion packet to the ThreadDispatch IOCompletionPort. * winnt_get_connection() *    Worker threads block on the ThreadDispatch IOCompletionPort awaiting  *    connections to service. */static void winnt_accept(void *listen_socket) {    static int num_completion_contexts = 0;    PCOMP_CONTEXT pCompContext;    DWORD BytesRead;    SOCKET nlsd;    int lasterror;    nlsd = (SOCKET) listen_socket;    while (1) {        pCompContext = NULL;        /* Grab a context off the queue */        apr_lock_acquire(qlock);        if (qhead) {            pCompContext = qhead;            qhead = qhead->next;            if (!qhead)                qtail = NULL;        }        apr_lock_release(qlock);        /* If we failed to grab a context off the queue, alloc one out of          * the child pool. There may be up to ap_threads_per_child contexts         * in the system at once.         */        if (!pCompContext) {            if (num_completion_contexts >= ap_threads_per_child) {                static int reported = 0;                if (!reported) {                    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, server_conf,                                 "Server ran out of threads to serve requests. Consider "                                 "raising the ThreadsPerChild setting");                    reported = 1;                }                Sleep(500);                continue;            }            pCompContext = (PCOMP_CONTEXT) apr_pcalloc(pchild, sizeof(COMP_CONTEXT));            pCompContext->Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);             if (pCompContext->Overlapped.hEvent == NULL) {                ap_log_error(APLOG_MARK,APLOG_ERR, apr_get_os_error(), server_conf,                             "winnt_accept: CreateEvent failed. Process will exit.");                // return -1;            }            pCompContext->accept_socket = INVALID_SOCKET;            num_completion_contexts++;        }    again:                    /* Create and initialize the accept socket */        if (pCompContext->accept_socket == INVALID_SOCKET) {            pCompContext->accept_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);                    if (pCompContext->accept_socket == INVALID_SOCKET) {                ap_log_error(APLOG_MARK,APLOG_ERR, apr_get_netos_error(), server_conf,                             "winnt_accept: socket() failed. Process will exit.");                // return -1;            }            /* SO_UPDATE_ACCEPT_CONTEXT is required for shutdown() to work */            if (setsockopt(pCompContext->accept_socket, SOL_SOCKET,                           SO_UPDATE_ACCEPT_CONTEXT, (char *)&nlsd,                           sizeof(nlsd))) {                ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_netos_error(), server_conf,                             "setsockopt(SO_UPDATE_ACCEPT_CONTEXT) failed.");                /* Not a failure condition. Keep running. */            }        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -