X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=server.c;h=8c61732592269301e22bd4ecfffc0c5cf5571ceb;hp=79e67818c87a1573b312c00091c8199f41c286ed;hb=a9126f461792a84c760162ecb25100f1593d427d;hpb=3781a3df94ce9bb28c98369df7a140fb4c086c23 diff --git a/server.c b/server.c index 79e67818..8c617325 100644 --- a/server.c +++ b/server.c @@ -59,15 +59,17 @@ * - Ring buffer: \ref ringbuffer.c, \ref ringbuffer.h, * - Hashing: \ref hash.h, \ref sha1.h, \ref sha1.c, * - Crypto: \ref crypt.c. - * + * - Forward error correction: \ref fec.c */ #include #include #include +#include #include "para.h" #include "error.h" +#include "crypt.h" #include "server.cmdline.h" #include "afh.h" #include "string.h" @@ -291,15 +293,32 @@ static void signal_post_select(struct sched *s, struct task *t) if (pid != mmd->afs_pid) continue; PARA_EMERG_LOG("fatal: afs died\n"); - goto genocide; + kill(0, SIGTERM); + goto cleanup; } break; /* die on sigint/sigterm. Kill all children too. */ case SIGINT: case SIGTERM: PARA_EMERG_LOG("terminating on signal %d\n", st->signum); -genocide: kill(0, SIGTERM); + /* + * We must wait for afs because afs catches SIGINT/SIGTERM. + * Before reacting to the signal, afs might want to use the + * shared memory area and the mmd mutex. If we destroy this + * mutex too early and afs tries to lock the shared memory + * area, the call to mutex_lock() will fail and terminate the + * afs process. This leads to dirty osl tables. + * + * There's no such problem with the other children of the + * server process (the command handlers) as these reset their + * SIGINT/SIGTERM handlers to the default action, i.e. these + * processes get killed immediately by the above kill(). + */ + PARA_INFO_LOG("waiting for afs (pid %d) to die\n", + (int)mmd->afs_pid); + waitpid(mmd->afs_pid, NULL, 0); +cleanup: free(mmd->afd.afhi.chunk_table); free(mmd->afd.afhi.info_string); close_listed_fds(); @@ -342,6 +361,8 @@ static void command_post_select(struct sched *s, struct task *t) int new_fd, ret, i; char *peer_name; pid_t child_pid; + uint32_t *chunk_table; + char *info_string; if (!FD_ISSET(sct->listen_fd, &s->rfds)) return; @@ -353,7 +374,16 @@ static void command_post_select(struct sched *s, struct task *t) PARA_INFO_LOG("got connection from %s, forking\n", peer_name); mmd->num_connects++; mmd->active_connections++; - random(); + /* The chunk table and the info_string are pointers located in the + * mmd struct that point to dynamically allocated memory that must be + * freed by the parent and the child. However, as the mmd struct is in + * a shared memory area, there's no guarantee that after the fork these + * pointers are still valid in child context. As these two pointers are + * not used in the child anyway, we save them to local variables and + * free the memory via that copy in the child. + */ + info_string = mmd->afd.afhi.info_string; + chunk_table = mmd->afd.afhi.chunk_table; child_pid = fork(); if (child_pid < 0) { ret = -ERRNO_TO_PARA_ERROR(errno); @@ -364,6 +394,9 @@ static void command_post_select(struct sched *s, struct task *t) /* parent keeps accepting connections */ return; } + /* mmd might already have changed at this point */ + free(info_string); + free(chunk_table); alarm(ALARM_TIMEOUT); close_listed_fds(); para_signal_shutdown(); @@ -406,35 +439,6 @@ err: exit(EXIT_FAILURE); } -static void init_random_seed(void) -{ - unsigned int seed; - int fd, ret = para_open("/dev/urandom", O_RDONLY, 0); - - if (ret < 0) - goto err; - fd = ret; - ret = read(fd, &seed, sizeof(seed)); - if (ret < 0) { - ret = -ERRNO_TO_PARA_ERROR(errno); - goto out; - } - if (ret != sizeof(seed)) { - ret = -ERRNO_TO_PARA_ERROR(EIO); - goto out; - } - srandom(seed); - ret = 1; -out: - close(fd); - if (ret >= 0) - return; -err: - PARA_EMERG_LOG("can not seed pseudo random number generator: %s\n", - para_strerror(-ret)); - exit(EXIT_FAILURE); -} - static int init_afs(void) { int ret, afs_server_socket[2]; @@ -442,7 +446,8 @@ static int init_afs(void) ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, afs_server_socket); if (ret < 0) exit(EXIT_FAILURE); - afs_socket_cookie = para_random((uint32_t)-1); + get_random_bytes_or_die((unsigned char *)&afs_socket_cookie, + sizeof(afs_socket_cookie)); mmd->afs_pid = fork(); if (mmd->afs_pid < 0) exit(EXIT_FAILURE); @@ -478,7 +483,7 @@ static void server_init(int argc, char **argv) int afs_socket; valid_fd_012(); - init_random_seed(); + init_random_seed_or_die(); /* parse command line options */ server_cmdline_parser_ext(argc, argv, &conf, ¶ms); HANDLE_VERSION_FLAG("server", conf);