Mercurial > dovecot > original-hg > dovecot-1.2
diff src/master/login-process.c @ 613:1906116a62ce HEAD
Finally support for handling each login connection in it's own process.
Enabled by default. Also a few bugfixes to master process.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 16 Nov 2002 07:21:21 +0200 |
parents | ab3590c3a7d9 |
children | e60620644af3 |
line wrap: on
line diff
--- a/src/master/login-process.c Sat Nov 16 07:19:03 2002 +0200 +++ b/src/master/login-process.c Sat Nov 16 07:21:21 2002 +0200 @@ -14,15 +14,19 @@ #include <unistd.h> #include <syslog.h> -typedef struct { +typedef struct _LoginProcess LoginProcess; + +struct _LoginProcess { + LoginProcess *prev_nonlisten, *next_nonlisten; int refcount; pid_t pid; int fd; IO io; OBuffer *outbuf; + unsigned int listening:1; unsigned int destroyed:1; -} LoginProcess; +}; typedef struct { LoginProcess *process; @@ -36,7 +40,10 @@ static int auth_id_counter; static Timeout to; -static HashTable *processes = NULL; + +static HashTable *processes; +static LoginProcess *oldest_nonlisten_process, *newest_nonlisten_process; +static unsigned int listening_processes; static void login_process_destroy(LoginProcess *p); static void login_process_unref(LoginProcess *p); @@ -103,6 +110,28 @@ return; } + if (client_fd == -1) { + /* just a notification that the login process isn't + listening for new connections anymore */ + if (!p->listening) { + i_error("login: received another \"not listening\" " + "notification"); + } else { + p->listening = FALSE; + listening_processes--; + + p->prev_nonlisten = newest_nonlisten_process; + + if (newest_nonlisten_process != NULL) + newest_nonlisten_process->next_nonlisten = p; + newest_nonlisten_process = p; + + if (oldest_nonlisten_process == NULL) + oldest_nonlisten_process = p; + } + return; + } + /* login process isn't trusted, validate all data to make sure it's not trying to exploit us */ if (!VALIDATE_STR(req.login_tag)) { @@ -125,7 +154,7 @@ if (auth_process == NULL) { i_error("login: Authentication process %u doesn't exist", req.auth_process); - auth_callback(NULL, &authreq); + auth_callback(NULL, authreq); } else { auth_process_request(auth_process, authreq->auth_id, req.cookie, auth_callback, authreq); @@ -142,26 +171,50 @@ p->refcount = 1; p->pid = pid; p->fd = fd; + p->listening = TRUE; p->io = io_add(fd, IO_READ, login_process_input, p); p->outbuf = o_buffer_create_file(fd, default_pool, sizeof(MasterReply)*10, IO_PRIORITY_DEFAULT, FALSE); hash_insert(processes, POINTER_CAST(pid), p); + listening_processes++; return p; } +void login_process_remove_from_lists(LoginProcess *p) +{ + if (p == oldest_nonlisten_process) + oldest_nonlisten_process = p->next_nonlisten; + else + p->prev_nonlisten->next_nonlisten = p->next_nonlisten; + + if (p == newest_nonlisten_process) + newest_nonlisten_process = p->prev_nonlisten; + else + p->next_nonlisten->prev_nonlisten = p->prev_nonlisten; + + p->next_nonlisten = p->prev_nonlisten = NULL; +} + static void login_process_destroy(LoginProcess *p) { if (p->destroyed) return; p->destroyed = TRUE; + if (p->listening) + listening_processes--; + o_buffer_close(p->outbuf); io_remove(p->io); (void)close(p->fd); + if (!p->listening) + login_process_remove_from_lists(p); + hash_remove(processes, POINTER_CAST(p->pid)); + login_process_unref(p); } @@ -180,6 +233,12 @@ pid_t pid; int fd[2]; + if (set_login_process_per_connection && + hash_size(processes)-listening_processes >= set_max_logging_users) { + if (oldest_nonlisten_process != NULL) + login_process_destroy(oldest_nonlisten_process); + } + if (set_login_uid == 0) i_fatal("Login process must not run as root"); @@ -249,8 +308,13 @@ if (set_disable_plaintext_auth) putenv("DISABLE_PLAINTEXT_AUTH=1"); - putenv((char *) t_strdup_printf("MAX_LOGGING_USERS=%d", - set_max_logging_users)); + if (set_login_process_per_connection) { + putenv("PROCESS_PER_CONNECTION=1"); + putenv("MAX_LOGGING_USERS=1"); + } else { + putenv((char *) t_strdup_printf("MAX_LOGGING_USERS=%d", + set_max_logging_users)); + } /* hide the path, it's ugly */ argv[0] = strrchr(set_login_executable, '/'); @@ -280,14 +344,17 @@ { /* create max. one process every second, that way if it keeps dying all the time we don't eat all cpu with fork()ing. */ - if (hash_size(processes) < set_login_processes_count) + if (listening_processes < set_login_processes_count) (void)create_login_process(); } void login_processes_init(void) { auth_id_counter = 0; - processes = hash_create(default_pool, 128, NULL, NULL); + listening_processes = 0; + oldest_nonlisten_process = newest_nonlisten_process = NULL; + + processes = hash_create(default_pool, 128, NULL, NULL); to = timeout_add(1000, login_processes_start_missing, NULL); }