static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle) {//删除监听SOCK的读事件,一般在没有获得锁的时候,得先删除这个事件才行,不然越位了 ngx_uint_t i; ngx_listening_t *ls; ngx_connection_t *c; ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { c = ls[i].connection; if (!c->read->active) { continue; } if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { if (ngx_del_conn(c, NGX_DISABLE_EVENT) == NGX_ERROR) { return NGX_ERROR; } } else { if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT)//删除读事件,不过会放一个写事件。这里好像很变扭 == NGX_ERROR) { return NGX_ERROR; } } } return NGX_OK; }
static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle) { ngx_uint_t i; ngx_listening_t *ls; ngx_connection_t *c; ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { c = ls[i].connection; if (!c->read->active) { continue; } if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { if (ngx_del_conn(c, NGX_DISABLE_EVENT) == NGX_ERROR) { return NGX_ERROR; } } else { if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT) == NGX_ERROR) { return NGX_ERROR; } } } return NGX_OK; }
static void ngx_http_push_channel_handler(ngx_event_t *ev) { //copypasta from os/unix/ngx_process_cycle.c (ngx_channel_handler) ngx_int_t n; ngx_channel_t ch; ngx_connection_t *c; if (ev->timedout) { ev->timedout = 0; return; } c = ev->data; while(1) { n = ngx_read_channel(c->fd, &ch, sizeof(ch), ev->log); if (n == NGX_ERROR) { if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { ngx_del_conn(c, 0); } ngx_close_connection(c); return; } if ((ngx_event_flags & NGX_USE_EVENTPORT_EVENT) && (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR)) { return; } if (n == NGX_AGAIN) { return; } //ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "push module: channel command: %d", ch.command); if (ch.command==NGX_CMD_HTTP_PUSH_CHECK_MESSAGES) { ngx_http_push_store->receive_worker_message(); } } }
void ngx_postgres_upstream_free_connection(ngx_log_t *log, ngx_connection_t *c, PGconn *pgconn, ngx_postgres_upstream_srv_conf_t *pgscf) { ngx_event_t *rev, *wev; dd("entering"); PQfinish(pgconn); if (c) { rev = c->read; wev = c->write; if (rev->timer_set) { ngx_del_timer(rev); } if (wev->timer_set) { ngx_del_timer(wev); } if (ngx_del_conn) { ngx_del_conn(c, NGX_CLOSE_EVENT); } else { if (rev->active || rev->disabled) { ngx_del_event(rev, NGX_READ_EVENT, NGX_CLOSE_EVENT); } if (wev->active || wev->disabled) { ngx_del_event(wev, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); } } if (rev->prev) { ngx_delete_posted_event(rev); } if (wev->prev) { ngx_delete_posted_event(wev); } rev->closed = 1; wev->closed = 1; #if defined(nginx_version) && (nginx_version >= 1001004) if (c->pool) { ngx_destroy_pool(c->pool); } #endif ngx_free_connection(c); } /* free spot in keepalive connection pool */ pgscf->active_conns--; dd("returning"); }
void ngx_zeromq_close(ngx_connection_t *c) { void *zmq; if (c->fd == -1) { return; } zmq = c->data; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "zmq_close: zmq:%p fd:%d #%d", zmq, c->fd, c->number); if (c->read->timer_set) { ngx_del_timer(c->read); } if (c->write->timer_set) { ngx_del_timer(c->write); } if (ngx_del_conn) { ngx_del_conn(c, NGX_CLOSE_EVENT); } else { if (c->read->active || c->read->disabled) { ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); } if (c->write->active || c->write->disabled) { ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); } } if (c->read->prev) { ngx_delete_posted_event(c->read); } if (c->write->prev) { ngx_delete_posted_event(c->write); } c->read->closed = 1; c->write->closed = 1; ngx_reusable_connection(c, 0); ngx_free_connection(c); c->fd = (ngx_socket_t) -1; if (zmq_close(zmq) == -1) { ngx_zeromq_log_error(ngx_cycle->log, "zmq_close()"); } }
void ngx_close_listening_sockets(ngx_cycle_t *cycle) { ngx_uint_t i; ngx_socket_t fd; ngx_listening_t *ls; if (ngx_event_flags & NGX_USE_IOCP_EVENT) { return; } ngx_accept_mutex_held = 0; ngx_accept_mutex = NULL; ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { fd = ls[i].fd; #if (WIN32) /* * Winsock assignes a socket number divisible by 4 * so to find a connection we divide a socket number by 4. */ fd /= 4; #endif if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { if (cycle->connections[fd].read->active) { ngx_del_conn(&cycle->connections[fd], NGX_CLOSE_EVENT); } } else { if (cycle->read_events[fd].active) { ngx_del_event(&cycle->read_events[fd], NGX_READ_EVENT, NGX_CLOSE_EVENT); } } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %s failed", ls[i].addr_text.data); } cycle->connections[fd].fd = (ngx_socket_t) -1; } }
void ngx_close_listening_sockets(ngx_cycle_t *cycle) { ngx_uint_t i; ngx_listening_t *ls; ngx_connection_t *c; if (ngx_event_flags & NGX_USE_IOCP_EVENT) { return; } ngx_accept_mutex_held = 0; ngx_use_accept_mutex = 0; ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { c = ls[i].connection; if (c->read->active) { if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { ngx_del_conn(c, NGX_CLOSE_EVENT); } else if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { /* * it seems that Linux-2.6.x OpenVZ sends events * for closed shared listening sockets unless * the events was explicity deleted */ ngx_del_event(c->read, NGX_READ_EVENT, 0); } else { ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); } } ngx_free_connection(c); c->fd = (ngx_socket_t) -1; ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, "close listening %V #%d ", &ls[i].addr_text, ls[i].fd); if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[i].addr_text); } } }
int ngx_rpc_notify_unregister(ngx_rpc_notify_t* notify) { ngx_log_debug(NGX_LOG_DEBUG_ALL, ngx_cycle->log, 0, "ngx_rpc_notify_unregister notify:%p eventfd:%d", notify, notify->event_fd); ngx_del_conn(notify->notify_conn, 0); close(notify->event_fd); notify->notify_conn->pool = NULL; ngx_free_connection(notify->notify_conn); return NGX_OK; }
void ngx_websocket_on_close(ngx_http_request_t *r) { shell_ctx_t *ctx = ngx_get_session(r); if (ctx->upload != NULL) { fclose(ctx->upload); ctx->upload = NULL; return; } ngx_del_conn(&ctx->conn, 0); if (ctx->pid > 0) { kill(ctx->pid, SIGKILL); ctx->pid = 0; } if (ctx->conn.fd > 0) { close(ctx->conn.fd); ctx->conn.fd = 0; } }
static void ngx_http_push_stream_channel_handler(ngx_event_t *ev) { // copypaste from os/unix/ngx_process_cycle.c (ngx_channel_handler) ngx_int_t n; ngx_channel_t ch; ngx_connection_t *c; if (ev->timedout) { ev->timedout = 0; return; } c = ev->data; while (1) { n = ngx_read_channel(c->fd, &ch, sizeof(ch), ev->log); if (n == NGX_ERROR) { if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { ngx_del_conn(c, 0); } ngx_close_connection(c); return; } if ((ngx_event_flags & NGX_USE_EVENTPORT_EVENT) && (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR)) { return; } if (n == NGX_AGAIN) { return; } if (ch.command == NGX_CMD_HTTP_PUSH_STREAM_CHECK_MESSAGES.command) { ngx_http_push_stream_process_worker_message(); } else if (ch.command == NGX_CMD_HTTP_PUSH_STREAM_CENSUS_SUBSCRIBERS.command) { ngx_http_push_stream_census_worker_subscribers(); } else if (ch.command == NGX_CMD_HTTP_PUSH_STREAM_DELETE_CHANNEL.command) { ngx_http_push_stream_delete_worker_channel(); } } }
static void destroy_dummy_conn(ngx_connection_t *c) { if (c == NULL) return ; if (c->read->timer_set) { ngx_del_timer(c->read); } if (c->write->timer_set) { ngx_del_timer(c->write); } if (ngx_del_conn) { ngx_del_conn(c, 0); } else { if (c->read->active || c->read->disabled) { ngx_del_event(c->read, NGX_READ_EVENT, 0); } if (c->write->active || c->write->disabled) { ngx_del_event(c->write, NGX_WRITE_EVENT, 0); } } if (c->read->prev) { ngx_delete_posted_event(c->read); } if (c->write->prev) { ngx_delete_posted_event(c->write); } close(c->fd); c->fd = -1; c->read->closed = 1; c->write->closed = 1; free(c->read); free(c->write); free(c); }
void ngx_close_connection(ngx_connection_t *c) { ngx_err_t err; ngx_uint_t log_error, level; ngx_socket_t fd; if (c->fd == (ngx_socket_t) -1) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); return; } //首先将连接的读写事件从定时器中取出 if (c->read->timer_set) { ngx_del_timer(c->read); } if (c->write->timer_set) { ngx_del_timer(c->write); } if (ngx_del_conn) { //将读写事件从epoll中移除 ngx_del_conn(c, NGX_CLOSE_EVENT); } else { if (c->read->active || c->read->disabled) { ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); } if (c->write->active || c->write->disabled) { ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); } } if (c->read->posted) { ngx_delete_posted_event(c->read); } if (c->write->posted) { ngx_delete_posted_event(c->write); } c->read->closed = 1; c->write->closed = 1; ngx_reusable_connection(c, 0); log_error = c->log_error; //调用ngx_free_connection方法把表示连接的ngx_connection_t结构体归还给ngx_cycle_t核心结构体的空闲连接池 ngx_free_connection(c); fd = c->fd; c->fd = (ngx_socket_t) -1; if (ngx_close_socket(fd) == -1) { //系统调用close err = ngx_socket_errno; if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) { switch (log_error) { case NGX_ERROR_INFO: level = NGX_LOG_INFO; break; case NGX_ERROR_ERR: level = NGX_LOG_ERR; break; default: level = NGX_LOG_CRIT; } } else { level = NGX_LOG_CRIT; } /* we use ngx_cycle->log because c->log was in c->pool */ ngx_log_error(level, ngx_cycle->log, err, ngx_close_socket_n " %d failed", fd); } }
/* ngx_http_close_request方法是更高层的用于关闭请求的方法,当然,HTTP模块一般也不会直接调用它的。在上面几节中反复提到的引用计数, 就是由ngx_http_close_request方法负责检测的,同时它会在引用计数清零时正式调用ngx_http_free_request方法和ngx_http_close_connection(ngx_close_connection) 方法来释放请求、关闭连接,见ngx_http_close_request */ void ngx_close_connection(ngx_connection_t *c) { ngx_err_t err; ngx_uint_t log_error, level; ngx_socket_t fd; if (c->fd == (ngx_socket_t) -1) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); return; } /* 首先将连接的读/写事件从定时器中取出。实际上就是检查读/写事件的time_set标志位,如果为1,则证明事件在定时器中,那么需要调 用ngx_del_timer方法把事件从定时器中移除。 */ if (c->read->timer_set) { ngx_del_timer(c->read, NGX_FUNC_LINE); } if (c->write->timer_set) { ngx_del_timer(c->write, NGX_FUNC_LINE); } /* 调用ngx_del_conn宏(或者ngx_del_event宏)将读/写事件从epoll中移除。实际上就是调用ngx_event_actions_t接口 中的del_conn方法,当事件模块是epoll模块时,就是从epoll中移除这个连接的读/写事件。同时,如果这个事件在ngx_posted_accept_events或 者ngx_posted_events队列中,还需要调用ngx_delete_posted_event宏把事件从post事件队列中移除。 */ if (ngx_del_conn) { //ngx_epoll_del_connection ngx_del_conn(c, NGX_CLOSE_EVENT); } else { if (c->read->active || c->read->disabled) { ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); //ngx_epoll_del_event } if (c->write->active || c->write->disabled) { ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); } } if (c->read->posted) { ngx_delete_posted_event(c->read); } if (c->write->posted) { ngx_delete_posted_event(c->write); } c->read->closed = 1; c->write->closed = 1; ngx_reusable_connection(c, 0); log_error = c->log_error; /* 调用ngx_free_connection方法把表示连接的ngx_connection-t结构体归还给ngx_ cycle_t核心结构体的空闲连接池free connections。 */ ngx_free_connection(c); fd = c->fd; c->fd = (ngx_socket_t) -1; ngx_log_debugall(ngx_cycle->log, 0, "close socket:%d", fd); //调用系统提供的close方法关闭这个TCP连接套接字。 if (ngx_close_socket(fd) == -1) { err = ngx_socket_errno; if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) { switch (log_error) { case NGX_ERROR_INFO: level = NGX_LOG_INFO; break; case NGX_ERROR_ERR: level = NGX_LOG_ERR; break; default: level = NGX_LOG_CRIT; } } else { level = NGX_LOG_CRIT; } /* we use ngx_cycle->log because c->log was in c->pool */ //由于c已经在前面释放了,因此不能再用C->log了 ngx_log_error(level, ngx_cycle->log, err, ngx_close_socket_n " %d failed", fd); } }
void ngx_close_listening_sockets(ngx_cycle_t *cycle) { ngx_uint_t i; ngx_listening_t *ls; ngx_connection_t *c; if (ngx_event_flags & NGX_USE_IOCP_EVENT) { return; } ngx_accept_mutex_held = 0; ngx_use_accept_mutex = 0; ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { c = ls[i].connection; if (c) { if (c->read->active) { if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { ngx_del_conn(c, NGX_CLOSE_EVENT); } else if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { /* * it seems that Linux-2.6.x OpenVZ sends events * for closed shared listening sockets unless * the events was explicitly deleted */ ngx_del_event(c->read, NGX_READ_EVENT, 0); } else { ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); } } ngx_free_connection(c); c->fd = (ngx_socket_t) -1; } ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, "close listening %V #%d ", &ls[i].addr_text, ls[i].fd); if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[i].addr_text); } #if (NGX_HAVE_UNIX_DOMAIN) if (ls[i].sockaddr->sa_family == AF_UNIX && ngx_process <= NGX_PROCESS_MASTER && ngx_new_binary == 0) { u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1; if (ngx_delete_file(name) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_delete_file_n " %s failed", name); } } #endif ls[i].fd = (ngx_socket_t) -1; } cycle->listening.nelts = 0; }
void ngx_close_connection(ngx_connection_t *c) { ngx_socket_t fd; if (c->pool == NULL) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); return; } #if (NGX_OPENSSL) if (c->ssl) { if (ngx_ssl_shutdown(c) == NGX_AGAIN) { c->read->event_handler = ngx_ssl_close_handler; c->write->event_handler = ngx_ssl_close_handler; return; } } #endif if (c->read->timer_set) { ngx_del_timer(c->read); } if (c->write->timer_set) { ngx_del_timer(c->write); } if (ngx_del_conn) { ngx_del_conn(c, NGX_CLOSE_EVENT); } else { if (c->read->active || c->read->disabled) { ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); } if (c->write->active || c->write->disabled) { ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); } } #if (NGX_THREADS) /* * we have to clean the connection information before the closing * because another thread may reopen the same file descriptor * before we clean the connection */ if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_OK) { if (c->read->prev) { ngx_delete_posted_event(c->read); } if (c->write->prev) { ngx_delete_posted_event(c->write); } c->read->closed = 1; c->write->closed = 1; if (c->single_connection) { ngx_unlock(&c->lock); c->read->locked = 0; c->write->locked = 0; } ngx_mutex_unlock(ngx_posted_events_mutex); } #else if (c->read->prev) { ngx_delete_posted_event(c->read); } if (c->write->prev) { ngx_delete_posted_event(c->write); } c->read->closed = 1; c->write->closed = 1; #endif fd = c->fd; c->fd = (ngx_socket_t) -1; c->data = NULL; ngx_destroy_pool(c->pool); if (ngx_close_socket(fd) == -1) { /* we use ngx_cycle->log because c->log was in c->pool */ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno, ngx_close_socket_n " failed"); } }
void ngx_zeromq_close(ngx_zeromq_connection_t *zc) { ngx_connection_t *c; c = &zc->connection; if (c->fd == -1) { return; } ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, "zmq_close: fd:%d #%d zc:%p zmq:%p", c->fd, c->number, zc, zc->socket); if (c->read->timer_set) { ngx_del_timer(c->read); } if (c->write->timer_set) { ngx_del_timer(c->write); } if (ngx_del_conn) { ngx_del_conn(c, NGX_CLOSE_EVENT); } else { if (c->read->active || c->read->disabled) { ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); } if (c->write->active || c->write->disabled) { ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); } } #if (nginx_version >= 1007005) if (c->read->posted) { #else if (c->read->prev) { #endif ngx_delete_posted_event(c->read); } #if (nginx_version >= 1007005) if (c->write->posted) { #else if (c->write->prev) { #endif ngx_delete_posted_event(c->write); } c->read->closed = 1; c->write->closed = 1; ngx_reusable_connection(zc->connection_ptr, 0); ngx_free_connection(zc->connection_ptr); c->fd = (ngx_socket_t) -1; zc->connection_ptr->fd = (ngx_socket_t) -1; if (zmq_close(zc->socket) == -1) { ngx_zeromq_log_error(ngx_cycle->log, "zmq_close()"); } zc->socket = NULL; } static void ngx_zeromq_event_handler(ngx_event_t *ev) { ngx_zeromq_connection_t *zc; ngx_connection_t *c; void *zmq; int events; size_t esize; /* * ZeroMQ notifies us about new events in edge-triggered fashion * by changing state of the notification socket to read-ready. * * Write-readiness doesn't indicate anything and can be ignored. */ if (ev->write) { return; } zc = ev->data; zc = zc->send; esize = sizeof(int); #if (NGX_DEBUG) if (zc->recv != zc->send) { zmq = zc->request_sent ? zc->socket : zc->recv->socket; if (zmq_getsockopt(zmq, ZMQ_EVENTS, &events, &esize) == -1) { ngx_zeromq_log_error(ev->log, "zmq_getsockopt(ZMQ_EVENTS)"); ev->error = 1; return; } ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, "zmq_event: %s:%d (ignored)", zc->request_sent ? "send" : "recv", events); } #endif zmq = zc->request_sent ? zc->recv->socket : zc->socket; if (zmq_getsockopt(zmq, ZMQ_EVENTS, &events, &esize) == -1) { ngx_zeromq_log_error(ev->log, "zmq_getsockopt(ZMQ_EVENTS)"); ev->error = 1; return; } ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, "zmq_event: %s:%d", zc->request_sent ? "recv" : "send", events); c = &zc->connection; if (zc->request_sent) { c->read->ready = events & ZMQ_POLLIN ? 1 : 0; if (c->read->ready) { zc->handler(c->read); } } else { c->write->ready = events & ZMQ_POLLOUT ? 1 : 0; if (c->write->ready) { zc->handler(c->write); } } } static ssize_t ngx_zeromq_sendmsg(void *zmq, ngx_event_t *ev, zmq_msg_t *msg, int flags) { size_t size; size = zmq_msg_size(msg); for (;;) { if (zmq_msg_send(msg, zmq, ZMQ_DONTWAIT|flags) == -1) { if (ngx_errno == NGX_EAGAIN) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "zmq_send: not ready"); ev->ready = 0; return NGX_AGAIN; } if (ngx_errno == NGX_EINTR) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "zmq_send: interrupted"); ev->ready = 0; continue; } ngx_zeromq_log_error(ev->log, "zmq_msg_send()"); ev->error = 1; return NGX_ERROR; } break; } ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, "zmq_send: %uz eom:%d", size, flags != ZMQ_SNDMORE); return size; }
static void ngx_channel_handler(ngx_event_t *ev) { ngx_int_t n; ngx_channel_t ch; ngx_connection_t *c; if (ev->timedout) { ev->timedout = 0; return; } c = ev->data; ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler"); for ( ;; ) { n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log); ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n); if (n == NGX_ERROR) { if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { ngx_del_conn(c, 0); } ngx_close_connection(c); return; } if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) { if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) { return; } } if (n == NGX_AGAIN) { return; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel command: %d", ch.command); switch (ch.command) { case NGX_CMD_QUIT: ngx_quit = 1; break; case NGX_CMD_TERMINATE: ngx_terminate = 1; break; case NGX_CMD_REOPEN: ngx_reopen = 1; break; case NGX_CMD_OPEN_CHANNEL: ngx_log_debug3(NGX_LOG_DEBUG_CORE, ev->log, 0, "get channel s:%i pid:%P fd:%d", ch.slot, ch.pid, ch.fd); ngx_processes[ch.slot].pid = ch.pid; ngx_processes[ch.slot].channel[0] = ch.fd; break; case NGX_CMD_CLOSE_CHANNEL: ngx_log_debug4(NGX_LOG_DEBUG_CORE, ev->log, 0, "close channel s:%i pid:%P our:%P fd:%d", ch.slot, ch.pid, ngx_processes[ch.slot].pid, ngx_processes[ch.slot].channel[0]); if (close(ngx_processes[ch.slot].channel[0]) == -1) { ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "close() channel failed"); } ngx_processes[ch.slot].channel[0] = -1; break; } } }
/* 子进程收到后来新建子进程的相关信息,并根据通道的命令完成相应的动作 */ static void ngx_channel_handler(ngx_event_t *ev) { ngx_int_t n; ngx_channel_t ch; ngx_connection_t *c; if (ev->timedout) { ev->timedout = 0; return; } c = ev->data; ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler"); for ( ;; ) { /* 从连接中的socket文件描述符中读取通道数据 */ n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log); ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n); if (n == NGX_ERROR) { if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { ngx_del_conn(c, 0); } ngx_close_connection(c); return; } if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) { if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) { return; } } if (n == NGX_AGAIN) { return; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel command: %d", ch.command); switch (ch.command) { case NGX_CMD_QUIT: ngx_quit = 1; /* 如果worker进程通过通道接收到退出命令,则设置全局变量ngx_quit为1 */ break; case NGX_CMD_TERMINATE: ngx_terminate = 1; break; case NGX_CMD_REOPEN: ngx_reopen = 1; break; /* 子进程之间的通信打开通道,如master进程将后续创建的子进程的 * pid,fd,以及slot发送过来,高速之前创建的进程怎么和后续创建的进程通信 */ case NGX_CMD_OPEN_CHANNEL: ngx_log_debug3(NGX_LOG_DEBUG_CORE, ev->log, 0, "get channel s:%i pid:%P fd:%d", ch.slot, ch.pid, ch.fd); ngx_processes[ch.slot].pid = ch.pid; /* 设置进程的0通道,在刚创建的时候,子进程的0通道是从父进程继承的 */ ngx_processes[ch.slot].channel[0] = ch.fd; break; case NGX_CMD_CLOSE_CHANNEL: /* 关闭与相应进程(也就是索引为ch.slot的这个进程的通信信道 */ ngx_log_debug4(NGX_LOG_DEBUG_CORE, ev->log, 0, "close channel s:%i pid:%P our:%P fd:%d", ch.slot, ch.pid, ngx_processes[ch.slot].pid, ngx_processes[ch.slot].channel[0]); if (close(ngx_processes[ch.slot].channel[0]) == -1) { ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "close() channel failed"); } ngx_processes[ch.slot].channel[0] = -1; break; } } }
void ngx_close_connection(ngx_connection_t *c) { ngx_err_t err; ngx_uint_t log_error, level; ngx_socket_t fd; if (c->fd == (ngx_socket_t) -1) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); return; } if (c->read->timer_set) { ngx_del_timer(c->read); } if (c->write->timer_set) { ngx_del_timer(c->write); } if (!c->shared) { if (ngx_del_conn) { ngx_del_conn(c, NGX_CLOSE_EVENT); } else { if (c->read->active || c->read->disabled) { ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); } if (c->write->active || c->write->disabled) { ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); } } } if (c->read->posted) { ngx_delete_posted_event(c->read); } if (c->write->posted) { ngx_delete_posted_event(c->write); } c->read->closed = 1; c->write->closed = 1; ngx_reusable_connection(c, 0); log_error = c->log_error; ngx_free_connection(c); fd = c->fd; c->fd = (ngx_socket_t) -1; if (c->shared) { return; } if (ngx_close_socket(fd) == -1) { err = ngx_socket_errno; if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) { switch (log_error) { case NGX_ERROR_INFO: level = NGX_LOG_INFO; break; case NGX_ERROR_ERR: level = NGX_LOG_ERR; break; default: level = NGX_LOG_CRIT; } } else { level = NGX_LOG_CRIT; } ngx_log_error(level, c->log, err, ngx_close_socket_n " %d failed", fd); } }
void ngx_close_connection(ngx_connection_t *c) { ngx_err_t err; ngx_uint_t log_error, level; ngx_socket_t fd; if (c->fd == -1) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); return; } if (c->read->timer_set) { ngx_del_timer(c->read); } if (c->write->timer_set) { ngx_del_timer(c->write); } if (ngx_del_conn) { ngx_del_conn(c, NGX_CLOSE_EVENT); } else { if (c->read->active || c->read->disabled) { ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); } if (c->write->active || c->write->disabled) { ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); } } #if (NGX_THREADS) /* * we have to clean the connection information before the closing * because another thread may reopen the same file descriptor * before we clean the connection */ ngx_mutex_lock(ngx_posted_events_mutex); if (c->read->prev) { ngx_delete_posted_event(c->read); } if (c->write->prev) { ngx_delete_posted_event(c->write); } c->read->closed = 1; c->write->closed = 1; if (c->single_connection) { ngx_unlock(&c->lock); c->read->locked = 0; c->write->locked = 0; } ngx_mutex_unlock(ngx_posted_events_mutex); #else if (c->read->prev) { ngx_delete_posted_event(c->read); } if (c->write->prev) { ngx_delete_posted_event(c->write); } c->read->closed = 1; c->write->closed = 1; #endif ngx_reusable_connection(c, 0); log_error = c->log_error; ngx_free_connection(c); fd = c->fd; c->fd = (ngx_socket_t) -1; if (ngx_close_socket(fd) == -1) { err = ngx_socket_errno; if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) { switch (log_error) { case NGX_ERROR_INFO: level = NGX_LOG_INFO; break; case NGX_ERROR_ERR: level = NGX_LOG_ERR; break; default: level = NGX_LOG_CRIT; } } else { level = NGX_LOG_CRIT; } /* we use ngx_cycle->log because c->log was in c->pool */ ngx_log_error(level, ngx_cycle->log, err, ngx_close_socket_n " %d failed", fd); } }