]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
master-child API change: Use a separate fd for tracking when master dies.
authorTimo Sirainen <tss@iki.fi>
Wed, 15 Dec 2010 17:07:01 +0000 (17:07 +0000)
committerTimo Sirainen <tss@iki.fi>
Wed, 15 Dec 2010 17:07:01 +0000 (17:07 +0000)
This works around a Linux performance problem where when one process writes
to status fd all the other processes of the same service type wake up.

src/lib-master/master-interface.h
src/lib-master/master-service.c
src/master/common.h
src/master/main.c
src/master/service-process.c

index 005abc5e871551b205d20382cac896a0255edba2..2a6a79f62ecf9c792679e4220a103182fdd7707c 100644 (file)
@@ -68,13 +68,16 @@ enum master_login_state {
 
 /* Shared pipe to master, used to send master_status reports */
 #define MASTER_STATUS_FD 5
+/* Pipe to master, used to detect when it dies. (MASTER_STATUS_FD would have
+   been fine for this, except it's inefficient in Linux) */
+#define MASTER_DEAD_FD 6
 /* First file descriptor where process is expected to be listening.
    The file descriptor count is given in -s parameter, defaulting to 1.
 
    master_status.available_count reports how many accept()s we're still
    accepting. Once no children are listening, master will do it and create
    new child processes when needed. */
-#define MASTER_LISTEN_FD_FIRST 6
+#define MASTER_LISTEN_FD_FIRST 7
 
 /* Timeouts: base everything on how long we can wait for login clients. */
 #define MASTER_LOGIN_TIMEOUT_SECS (3*60)
index 5925bb63fba98d27ca97c519b712ee0cf2a8bf27..250f479171df0db24242b6700f5ba980ff765ec9 100644 (file)
@@ -375,7 +375,7 @@ void master_service_init_finish(struct master_service *service)
                        master_service_set_service_count(service, count);
 
                /* start listening errors for status fd, it means master died */
-               service->io_status_error = io_add(MASTER_STATUS_FD, IO_ERROR,
+               service->io_status_error = io_add(MASTER_DEAD_FD, IO_ERROR,
                                                  master_status_error, service);
        } else {
                master_service_set_client_limit(service, 1);
index ee7fc8beeceb37228b8d71cde52745643df1532c..00ea6e17f63f235d150468f2b9b39aa896dd689f 100644 (file)
@@ -9,7 +9,7 @@ extern uid_t master_uid;
 extern gid_t master_gid;
 extern bool core_dumps_disabled;
 extern const char *ssl_manual_key_password;
-extern int null_fd;
+extern int null_fd, master_dead_pipe_fd[2];
 extern struct service_list *services;
 
 void process_exec(const char *cmd, const char *extra_args[]) ATTR_NORETURN;
index 350c9ca2415b62fee69ffbe09617484c382d8902..59bbec73a1e074663f3a33589e2044c570959902 100644 (file)
@@ -42,7 +42,7 @@ uid_t master_uid;
 gid_t master_gid;
 bool core_dumps_disabled;
 const char *ssl_manual_key_password;
-int null_fd;
+int null_fd, master_dead_pipe_fd[2];
 struct service_list *services;
 
 static char *pidfile_path;
@@ -412,7 +412,7 @@ static void main_init(const struct master_settings *set)
         lib_signals_set_handler(SIGUSR1, TRUE, sig_log_reopen, NULL);
         lib_signals_set_handler(SIGCHLD, TRUE, sig_reap_children, NULL);
         lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
-        lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
+       lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
 
        create_pid_file(pidfile_path);
        create_config_symlink(set);
@@ -712,6 +712,10 @@ int main(int argc, char *argv[])
                        i_fatal("Can't open /dev/null: %m");
                fd_close_on_exec(null_fd, TRUE);
        } while (null_fd <= STDERR_FILENO);
+       if (pipe(master_dead_pipe_fd) < 0)
+               i_fatal("pipe() failed: %m");
+       fd_close_on_exec(master_dead_pipe_fd[0], TRUE);
+       fd_close_on_exec(master_dead_pipe_fd[1], TRUE);
 
        set = master_settings_read();
        if (ask_key_pass) {
index de2a12ecd644cdf9d547d95a473f215cff2ca906..38d7f18e7029fec9c3f089ab628f2af1fff0058a 100644 (file)
@@ -116,6 +116,7 @@ service_dup_fds(struct service *service)
                break;
        }
        dup2_append(&dups, service->status_fd[1], MASTER_STATUS_FD);
+       dup2_append(&dups, master_dead_pipe_fd[1], MASTER_DEAD_FD);
 
        if (service->type == SERVICE_TYPE_LOG) {
                /* keep stderr as-is. this is especially important when