static void connect_event(int unused_event, void *context) { int sock = CAST_ANY_PTR_TO_INT(context); struct sockaddr_storage ss; SOCKADDR_SIZE len = sizeof(ss); struct sockaddr *sa = (struct sockaddr *) &ss; SINK_STATE *state; int fd; if ((fd = accept(sock, sa, &len)) >= 0) { if (msg_verbose) msg_info("connect (%s)", #ifdef AF_LOCAL sa->sa_family == AF_LOCAL ? "AF_LOCAL" : #else sa->sa_family == AF_UNIX ? "AF_UNIX" : #endif sa->sa_family == AF_INET ? "AF_INET" : #ifdef AF_INET6 sa->sa_family == AF_INET6 ? "AF_INET6" : #endif "unknown protocol family"); non_blocking(fd, NON_BLOCKING); state = (SINK_STATE *) mymalloc(sizeof(*state)); state->stream = vstream_fdopen(fd, O_RDWR); vstream_tweak_sock(state->stream); netstring_setup(state->stream, var_tmout); event_enable_read(fd, read_length, (void *) state); } }
static void single_server_accept_inet(int unused_event, void *context) { int listen_fd = CAST_ANY_PTR_TO_INT(context); int time_left = -1; int fd; /* * Be prepared for accept() to fail because some other process already * got the connection. We use select() + accept(), instead of simply * blocking in accept(), because we must be able to detect that the * master process has gone away unexpectedly. */ if (var_idle_limit > 0) time_left = event_cancel_timer(single_server_timeout, (void *) 0); if (single_server_pre_accept) single_server_pre_accept(single_server_name, single_server_argv); fd = inet_accept(listen_fd); if (single_server_lock != 0 && myflock(vstream_fileno(single_server_lock), INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0) msg_fatal("select unlock: %m"); if (fd < 0) { if (errno != EAGAIN) msg_error("accept connection: %m"); if (time_left >= 0) event_request_timer(single_server_timeout, (void *) 0, time_left); return; } single_server_wakeup(fd, (HTABLE *) 0); }
static void multi_server_accept_inet(int unused_event, void *context) { int listen_fd = CAST_ANY_PTR_TO_INT(context); int time_left = -1; int fd; /* * Be prepared for accept() to fail because some other process already * got the connection (the number of processes competing for clients is * kept small, so this is not a "thundering herd" problem). If the * accept() succeeds, be sure to disable non-blocking I/O, in order to * minimize confusion. */ if (client_count == 0 && var_idle_limit > 0) time_left = event_cancel_timer(multi_server_timeout, (void *) 0); if (multi_server_pre_accept) multi_server_pre_accept(multi_server_name, multi_server_argv); fd = inet_accept(listen_fd); if (multi_server_lock != 0 && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0) msg_fatal("select unlock: %m"); if (fd < 0) { if (errno != EAGAIN) msg_error("accept connection: %m"); if (time_left >= 0) event_request_timer(multi_server_timeout, (void *) 0, time_left); return; } multi_server_wakeup(fd, (HTABLE *) 0); }
static void trigger_server_accept_pass(int unused_event, void *context) { const char *myname = "trigger_server_accept_pass"; int listen_fd = CAST_ANY_PTR_TO_INT(context); int time_left = 0; int fd; if (msg_verbose) msg_info("%s: trigger arrived", myname); /* * Read a message from a socket. Be prepared for accept() to fail because * some other process already got the connection. The socket is * non-blocking so we won't get stuck when multiple processes wake up. * Don't get stuck when the client connects but sends no data. Restart * the idle timer if this was a false alarm. */ if (var_idle_limit > 0) time_left = event_cancel_timer(trigger_server_timeout, (void *) 0); if (trigger_server_pre_accept) trigger_server_pre_accept(trigger_server_name, trigger_server_argv); fd = pass_accept(listen_fd); if (trigger_server_lock != 0 && myflock(vstream_fileno(trigger_server_lock), INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0) msg_fatal("select unlock: %m"); if (fd < 0) { if (errno != EAGAIN) msg_error("accept connection: %m"); if (time_left >= 0) event_request_timer(trigger_server_timeout, (void *) 0, time_left); return; } close_on_exec(fd, CLOSE_ON_EXEC); if (read_wait(fd, 10) == 0) trigger_server_wakeup(fd); else if (time_left >= 0) event_request_timer(trigger_server_timeout, (void *) 0, time_left); close(fd); }
static void trigger_server_accept_fifo(int unused_event, void *context) { const char *myname = "trigger_server_accept_fifo"; int listen_fd = CAST_ANY_PTR_TO_INT(context); if (trigger_server_lock != 0 && myflock(vstream_fileno(trigger_server_lock), INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0) msg_fatal("select unlock: %m"); if (msg_verbose) msg_info("%s: trigger arrived", myname); /* * Read whatever the other side wrote into the FIFO. The FIFO read end is * non-blocking so we won't get stuck when multiple processes wake up. */ if (trigger_server_pre_accept) trigger_server_pre_accept(trigger_server_name, trigger_server_argv); trigger_server_wakeup(listen_fd); }