X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=command.c;h=aea48146a38cefd7aeb22ea2994c9d53b5633c08;hb=0c35f5c1692909134436cedac65b7c872a0b0867;hp=cd24c0350ef90fbeccf713325738a6b03eba1000;hpb=0b786d977ded3c3922e851e5b8d60837b43469b9;p=paraslash.git diff --git a/command.c b/command.c index cd24c035..aea48146 100644 --- a/command.c +++ b/command.c @@ -49,9 +49,14 @@ static const char * const server_command_perms_txt[] = {LSG_SERVER_CMD_AUX_INFOS extern int mmd_mutex; extern struct misc_meta_data *mmd; int send_afs_status(struct command_context *cc, int parser_friendly); +static bool subcmd_should_die; -static void dummy(__a_unused int s) +static void command_handler_sighandler(int s) { + if (s != SIGTERM) + return; + PARA_EMERG_LOG("terminating on signal %d\n", SIGTERM); + subcmd_should_die = true; } /* @@ -492,9 +497,21 @@ static int com_stat(struct command_context *cc, struct lls_parse_result *lpr) bool parser_friendly = SERVER_CMD_OPT_GIVEN(STAT, PARSER_FRIENDLY, lpr) > 0; uint32_t num = SERVER_CMD_UINT32_VAL(STAT, NUM, lpr); + const struct timespec ts = {.tv_sec = 50, .tv_nsec = 0}; - para_sigaction(SIGUSR1, dummy); + para_sigaction(SIGINT, SIG_IGN); + para_sigaction(SIGUSR1, command_handler_sighandler); + para_sigaction(SIGTERM, command_handler_sighandler); + /* + * Simply checking subcmd_should_die is racy because a signal may + * arrive after the check but before the subsequent call to sleep(3). + * If this happens, sleep(3) would not be interrupted by the signal. + * To avoid this we block SIGTERM here and allow it to arrive only + * while we sleep. + */ + para_block_signal(SIGTERM); for (;;) { + sigset_t set; /* * Copy the mmd structure to minimize the time we hold the mmd * lock. @@ -517,7 +534,15 @@ static int com_stat(struct command_context *cc, struct lls_parse_result *lpr) ret = 1; if (num > 0 && !--num) goto out; - sleep(50); + sigemptyset(&set); /* empty set means: unblock all signals */ + /* + * pselect(2) allows to atomically unblock signals, then go to + * sleep. Calling sigprocmask(2) followed by sleep(3) would + * open a race window similar to the one described above. + */ + pselect(1, NULL, NULL, NULL, &ts, &set); + if (subcmd_should_die) + goto out; ret = -E_SERVER_CRASH; if (getppid() == 1) goto out; @@ -759,7 +784,7 @@ struct connection_features { int dummy; /* none at the moment */ }; -static int parse_auth_request(char *buf, int len, struct user **u, +static int parse_auth_request(char *buf, int len, const struct user **u, struct connection_features *cf) { int ret; @@ -793,7 +818,7 @@ static int parse_auth_request(char *buf, int len, struct user **u, } } PARA_DEBUG_LOG("received auth request for user %s\n", username); - *u = lookup_user(username); + *u = user_list_lookup(username); ret = 1; out: free_argv(features); @@ -877,7 +902,7 @@ static int run_command(struct command_context *cc, struct iovec *iov) * * \sa alarm(2), \ref crypt.c, \ref crypt.h. */ -__noreturn void handle_connect(int fd) +int handle_connect(int fd) { int ret; unsigned char rand_buf[CHALLENGE_SIZE + 2 * SESSION_KEY_LEN]; @@ -987,5 +1012,5 @@ out: } sc_free(cc->scc.recv); sc_free(cc->scc.send); - exit(ret < 0? EXIT_FAILURE : EXIT_SUCCESS); + return ret; }