static void single_server_accept_local(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 = LOCAL_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_local(int unused_event, char *context) { int listen_fd = CAST_CHAR_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, (char *) 0); if (multi_server_pre_accept) multi_server_pre_accept(multi_server_name, multi_server_argv); fd = LOCAL_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, (char *) 0, time_left); return; } multi_server_wakeup(fd, (HTABLE *) 0); }
static void trigger_server_accept_local(int unused_event, char *context) { const char *myname = "trigger_server_accept_local"; int listen_fd = CAST_CHAR_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, (char *) 0); if (trigger_server_pre_accept) trigger_server_pre_accept(trigger_server_name, trigger_server_argv); fd = LOCAL_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, (char *) 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, (char *) 0, time_left); close(fd); }