summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2008-07-07 11:58:55 +0000
committerIgor Sysoev <igor@sysoev.ru>2008-07-07 11:58:55 +0000
commit4012d9909c4f15c5aa6b1feedcb1abfbb7575dc3 (patch)
tree18035f264bf5dce4b7c9521c19418441ead3defd
parent22a5d849701071c13f6a566ab640f8088f72c58e (diff)
downloadnginx-4012d9909c4f15c5aa6b1feedcb1abfbb7575dc3.tar.gz
r1901, r1902, r2032 merge:
bugfixes in channel: *) avoid endless loop if epoll is used *) use CMSG_LEN(), this fixes an alert "sendmsg() failed (9: Bad file descriptor)" on some 64-bit platforms *) read channel until EAGAIN
-rw-r--r--src/os/unix/ngx_channel.c4
-rw-r--r--src/os/unix/ngx_freebsd_config.h7
-rw-r--r--src/os/unix/ngx_posix_config.h7
-rw-r--r--src/os/unix/ngx_process_cycle.c91
4 files changed, 64 insertions, 45 deletions
diff --git a/src/os/unix/ngx_channel.c b/src/os/unix/ngx_channel.c
index 62ea7cc30..f0f337d06 100644
--- a/src/os/unix/ngx_channel.c
+++ b/src/os/unix/ngx_channel.c
@@ -33,7 +33,7 @@ ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
msg.msg_control = (caddr_t) &cmsg;
msg.msg_controllen = sizeof(cmsg);
- cmsg.cm.cmsg_len = sizeof(cmsg);
+ cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));
cmsg.cm.cmsg_level = SOL_SOCKET;
cmsg.cm.cmsg_type = SCM_RIGHTS;
*(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
@@ -138,7 +138,7 @@ ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, ngx_log_t *log)
if (ch->command == NGX_CMD_OPEN_CHANNEL) {
- if (cmsg.cm.cmsg_len < (socklen_t) sizeof(cmsg)) {
+ if (cmsg.cm.cmsg_len < (socklen_t) CMSG_LEN(sizeof(int))) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"recvmsg() returned too small ancillary data");
return NGX_ERROR;
diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h
index 818e230ba..24dcdcb46 100644
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -48,11 +48,16 @@
#if __FreeBSD_version < 400017
-/* FreeBSD 3.x has no CMSG_SPACE() at all and has the broken CMSG_DATA() */
+/*
+ * FreeBSD 3.x has no CMSG_SPACE() and CMSG_LEN() and has the broken CMSG_DATA()
+ */
#undef CMSG_SPACE
#define CMSG_SPACE(l) (ALIGN(sizeof(struct cmsghdr)) + ALIGN(l))
+#undef CMSG_LEN
+#define CMSG_LEN(l) (ALIGN(sizeof(struct cmsghdr)) + (l))
+
#undef CMSG_DATA
#define CMSG_DATA(cmsg) ((u_char *)(cmsg) + ALIGN(sizeof(struct cmsghdr)))
diff --git a/src/os/unix/ngx_posix_config.h b/src/os/unix/ngx_posix_config.h
index 49c3c4d6c..37176e0d2 100644
--- a/src/os/unix/ngx_posix_config.h
+++ b/src/os/unix/ngx_posix_config.h
@@ -110,11 +110,16 @@
#include <sys/param.h> /* ALIGN() */
-/* FreeBSD 3.x has no CMSG_SPACE() at all and has the broken CMSG_DATA() */
+/*
+ * FreeBSD 3.x has no CMSG_SPACE() and CMSG_LEN() and has the broken CMSG_DATA()
+ */
#undef CMSG_SPACE
#define CMSG_SPACE(l) (ALIGN(sizeof(struct cmsghdr)) + ALIGN(l))
+#undef CMSG_LEN
+#define CMSG_LEN(l) (ALIGN(sizeof(struct cmsghdr)) + (l))
+
#undef CMSG_DATA
#define CMSG_DATA(cmsg) ((u_char *)(cmsg) + ALIGN(sizeof(struct cmsghdr)))
diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c
index 631597ef4..338987fb0 100644
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -1055,65 +1055,74 @@ ngx_channel_handler(ngx_event_t *ev)
ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler");
- n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
+ for ( ;; ) {
- ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n);
+ n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
- if (n == NGX_ERROR) {
- ngx_close_connection(c);
- return;
- }
+ 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);
+ }
- if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {
- if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
+ ngx_close_connection(c);
return;
}
- }
- if (n == NGX_AGAIN) {
- return;
- }
+ if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {
+ if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
+ return;
+ }
+ }
- ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,
- "channel command: %d", ch.command);
+ if (n == NGX_AGAIN) {
+ return;
+ }
- switch (ch.command) {
+ ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,
+ "channel command: %d", ch.command);
- case NGX_CMD_QUIT:
- ngx_quit = 1;
- break;
+ switch (ch.command) {
- case NGX_CMD_TERMINATE:
- ngx_terminate = 1;
- break;
+ case NGX_CMD_QUIT:
+ ngx_quit = 1;
+ break;
- case NGX_CMD_REOPEN:
- ngx_reopen = 1;
- break;
+ case NGX_CMD_TERMINATE:
+ ngx_terminate = 1;
+ break;
- case NGX_CMD_OPEN_CHANNEL:
+ case NGX_CMD_REOPEN:
+ ngx_reopen = 1;
+ break;
- ngx_log_debug3(NGX_LOG_DEBUG_CORE, ev->log, 0,
- "get channel s:%i pid:%P fd:%d", ch.slot, ch.pid, ch.fd);
+ case NGX_CMD_OPEN_CHANNEL:
- ngx_processes[ch.slot].pid = ch.pid;
- ngx_processes[ch.slot].channel[0] = ch.fd;
- break;
+ ngx_log_debug3(NGX_LOG_DEBUG_CORE, ev->log, 0,
+ "get channel s:%i pid:%P fd:%d",
+ ch.slot, ch.pid, ch.fd);
- case NGX_CMD_CLOSE_CHANNEL:
+ ngx_processes[ch.slot].pid = ch.pid;
+ ngx_processes[ch.slot].channel[0] = ch.fd;
+ break;
- 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]);
+ case NGX_CMD_CLOSE_CHANNEL:
- if (close(ngx_processes[ch.slot].channel[0]) == -1) {
- ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
- "close() channel failed");
- }
+ 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]);
- ngx_processes[ch.slot].channel[0] = -1;
- break;
+ 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;
+ }
}
}