diff options
Diffstat (limited to '')
-rw-r--r-- | src/mds-server/mds-server.c | 142 | ||||
-rw-r--r-- | src/mds-server/mds-server.h | 15 |
2 files changed, 111 insertions, 46 deletions
diff --git a/src/mds-server/mds-server.c b/src/mds-server/mds-server.c index 819c9c5..c354134 100644 --- a/src/mds-server/mds-server.c +++ b/src/mds-server/mds-server.c @@ -71,11 +71,17 @@ static char** argv; static volatile sig_atomic_t running = 1; /** - * Non-zero when the program is about to re-exec + * Non-zero when the program is about to re-exec. + * Most at all times be at least as true as `terminating`. */ static volatile sig_atomic_t reexecing = 0; /** + * Non-zero when the program is about to terminate + */ +static volatile sig_atomic_t terminating = 0; + +/** * The number of running slaves */ static int running_slaves = 0; @@ -212,7 +218,7 @@ int main(int argc_, char** argv_) if (reexec) { is_respawn = 1; - eprint("re-exec:ing done."); + eprint("re-exec performed."); } @@ -251,12 +257,13 @@ int main(int argc_, char** argv_) } #define __free(I) \ - if (I <= 0) fd_table_destroy(&client_map, NULL, NULL); \ - if (I <= 1) linked_list_destroy(&client_list); \ - if (I <= 2) pthread_mutex_destroy(&slave_mutex); \ - if (I <= 3) pthread_cond_destroy(&slave_cond); \ - if (I <= 4) pthread_mutex_destroy(&modify_mutex); \ - if (I <= 5) pthread_cond_destroy(&modify_cond) + if (I >= 0) fd_table_destroy(&client_map, NULL, NULL); \ + if (I >= 1) linked_list_destroy(&client_list); \ + if (I >= 2) pthread_mutex_destroy(&slave_mutex); \ + if (I >= 3) pthread_cond_destroy(&slave_cond); \ + if (I >= 4) pthread_mutex_destroy(&modify_mutex); \ + if (I >= 5) pthread_cond_destroy(&modify_cond); \ + if (I >= 6) hash_table_destroy(&modify_map, NULL, NULL) /* Create list and table of clients. */ @@ -289,6 +296,14 @@ int main(int argc_, char** argv_) return 1; } + /* Implement clean exit on SIGTERM. */ + if (xsigaction(SIGTERM, sigterm_trap) < 0) + { + perror(*argv); + __free(1); + return 1; + } + /* Create mutex and condition for slave counter. */ if ((errno = pthread_mutex_init(&slave_mutex, NULL)) != 0) { @@ -351,7 +366,7 @@ int main(int argc_, char** argv_) } /* Accepting incoming connections. */ - while (running && (reexecing == 0)) + while (running && (terminating == 0)) { /* Accept connection. */ int client_fd = accept(socket_fd, NULL, NULL); @@ -363,8 +378,8 @@ int main(int argc_, char** argv_) { case EINTR: /* Interrupted. */ - if (reexecing) - goto reexec; + if (terminating) + goto terminate; break; case ECONNABORTED: @@ -392,19 +407,20 @@ int main(int argc_, char** argv_) with_mutex(slave_mutex, running_slaves--;); } } + + terminate: + if (reexecing) goto reexec; - - /* Wait for all slaves to close. */ + /* Join with all slaves threads. */ with_mutex(slave_mutex, while (running_slaves > 0) pthread_cond_wait(&slave_cond, &slave_mutex);); - /* Release resources. */ __free(9999); - + #undef __free return 0; @@ -571,10 +587,17 @@ void* slave_loop(void* data) goto fail; } + /* Implement clean exit on SIGTERM. */ + if (xsigaction(SIGTERM, sigterm_trap) < 0) + { + perror(*argv); + goto fail; + } + /* Fetch messages from the slave. */ if (information->open) - while (reexecing == 0) + while (terminating == 0) { /* Send queued multicast messages. */ if (information->multicasts_count > 0) @@ -628,7 +651,7 @@ void* slave_loop(void* data) if (r == 0) { if (message_received(information) == 1) - goto reexec; + goto terminate; } else if (r == -2) @@ -641,7 +664,7 @@ void* slave_loop(void* data) r = mds_message_read(&(information->message), socket_fd); if (r == 0) if (message_received(information)) - goto reexec; + goto terminate; information->open = 0; /* Connection closed. */ break; @@ -649,8 +672,8 @@ void* slave_loop(void* data) else if (errno == EINTR) { /* Stop the thread if we are re-exec:ing the server. */ - if (reexecing) - goto reexec; + if (terminating) + goto terminate; } else { @@ -659,8 +682,8 @@ void* slave_loop(void* data) } } /* Stop the thread if we are re-exec:ing the server. */ - if (reexecing) - goto reexec; + if (terminating) + goto terminate; /* Multicast information about the client closing. */ @@ -695,7 +718,7 @@ void* slave_loop(void* data) return NULL; - reexec: + terminate: /* Tell the master thread that the slave has closed, this is done because re-exec causes a race-condition between the acception of a slave and the execution @@ -760,7 +783,7 @@ int message_received(client_t* client) pthread_mutex_lock(&(modify_mutex)); while (hash_table_contains_key(&modify_map, (size_t)modify_id) == 0) { - if (reexecing) + if (terminating) { pthread_mutex_unlock(&(modify_mutex)); return 1; @@ -1364,7 +1387,7 @@ void multicast_message(multicast_t* multicast) /* Stop if we are re-exec:ing, or continue to next recipient on error. */ if (n > 0) { - if (reexecing) + if (terminating) return; else continue; @@ -1402,14 +1425,14 @@ void multicast_message(multicast_t* multicast) for (;;) { pthread_cond_timedwait(&slave_cond, &slave_mutex, &timeout); - if ((client->modify_message != NULL) && reexecing) + if ((client->modify_message != NULL) && terminating) break; } - if (reexecing == 0) + if (terminating == 0) hash_table_remove(&modify_map, (size_t)modify_id); } ); - if (reexecing) + if (terminating) return; /* Act upon the reply. */ @@ -1528,29 +1551,56 @@ void sigusr1_trap(int signo) { if (reexecing == 0) { - pthread_t current_thread; - ssize_t node; - - reexecing = 1; - current_thread = pthread_self(); - - eprint("re-exec:ing queue."); - - if (pthread_equal(current_thread, master_thread) == 0) - pthread_kill(master_thread, signo); - - with_mutex(slave_mutex, - foreach_linked_list_node (client_list, node) - { - client_t* value = (client_t*)(void*)(client_list.values[node]); - if (pthread_equal(current_thread, value->thread) == 0) - pthread_kill(value->thread, signo); - }); + terminating = reexecing = 1; + eprint("re-exec signal received."); + signal_all(signo); } } /** + * Called with the signal SIGTERM is caught. + * This function should cue a termination of the program. + * + * @param signo The caught signal + */ +void sigterm_trap(int signo) +{ + if (terminating == 0) + { + terminating = 1; + eprint("terminate signal received."); + signal_all(signo); + } +} + + +/** + * Send a singal to all threads except the current thread + * + * @param signo The signal + */ +void signal_all(int signo) +{ + pthread_t current_thread; + ssize_t node; + + current_thread = pthread_self(); + + if (pthread_equal(current_thread, master_thread) == 0) + pthread_kill(master_thread, signo); + + with_mutex(slave_mutex, + foreach_linked_list_node (client_list, node) + { + client_t* value = (client_t*)(void*)(client_list.values[node]); + if (pthread_equal(current_thread, value->thread) == 0) + pthread_kill(value->thread, signo); + }); +} + + +/** * Marshal the server's state into a file * * @param fd The file descriptor diff --git a/src/mds-server/mds-server.h b/src/mds-server/mds-server.h index c2e8404..43662d7 100644 --- a/src/mds-server/mds-server.h +++ b/src/mds-server/mds-server.h @@ -86,6 +86,21 @@ void run_initrc(char** args); void sigusr1_trap(int signo); /** + * Called with the signal SIGTERM is caught. + * This function should cue a termination of the program. + * + * @param signo The caught signal + */ +void sigterm_trap(int signo); + +/** + * Send a singal to all threads except the current thread + * + * @param signo The signal + */ +void signal_all(int signo); + +/** * Marshal the server's state into a file * * @param fd The file descriptor |