* - 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 <signal.h>
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();
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;
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);
/* 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();