summaryrefslogtreecommitdiffstats
path: root/src/server/server.c
diff options
context:
space:
mode:
authorSimon Rettberg2019-08-28 13:07:13 +0200
committerSimon Rettberg2019-08-28 13:07:13 +0200
commitac1bf45ebdd630fbc9ad2c1fa3c0ea99f5206799 (patch)
tree951388f8267c0194a142bf13d99b947ee7f820e6 /src/server/server.c
parent[SERVER] Remove old comments (diff)
downloaddnbd3-ac1bf45ebdd630fbc9ad2c1fa3c0ea99f5206799.tar.gz
dnbd3-ac1bf45ebdd630fbc9ad2c1fa3c0ea99f5206799.tar.xz
dnbd3-ac1bf45ebdd630fbc9ad2c1fa3c0ea99f5206799.zip
[SERVER] Make signal handling more POSIX
According to POSIX, a signal sent to a PID can be delivered to an arbitrary thread of that process that hasn't the signal blocked. This seens to never happen on Linux, but would mess things up since the code expected the main signal handler to only be executed by the main thread. This should now be fixed by examining the destination PID of the signal as well as the ID of the thread currently running the signal handler. If we notice the signal wasn't sent by our own PID and the handler is not currently run by the main thread, we re-send the signal to the main thread. Otherwise, if the signal was sent by our own PID but the handler is not run in the main thread, do nothing. This way we can use pthread_kill() to wake up threads that might be stuck in a blocking syscall when it's time to shut down.
Diffstat (limited to 'src/server/server.c')
-rw-r--r--src/server/server.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/src/server/server.c b/src/server/server.c
index 1cdd2ab..0dddea7 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -37,6 +37,8 @@
#include <signal.h>
#include <getopt.h>
#include <assert.h>
+#include <sys/types.h>
+#include <unistd.h>
#define LONGOPT_CRC4 1000
#define LONGOPT_ASSERT 1001
@@ -60,6 +62,7 @@ static _Atomic(job_t *) newJob;
static bool hasTimerThread = false;
static pthread_t timerThread;
+static pid_t mainPid;
static pthread_t mainThread;
#define DEFAULT_TIMER_TIMEOUT (60)
@@ -138,7 +141,7 @@ _Noreturn static void dnbd3_cleanup()
logadd( LOG_INFO, "Cleanup..." );
if ( hasTimerThread ) {
- pthread_kill( timerThread, SIGHUP );
+ pthread_kill( timerThread, SIGINT );
thread_join( timerThread, NULL );
}
@@ -162,6 +165,8 @@ _Noreturn static void dnbd3_cleanup()
// Wait for clients to disconnect
net_waitForAllDisconnected();
+ threadpool_waitEmpty();
+
// Clean up images
retries = 5;
while ( !image_tryFreeAll() && --retries > 0 ) {
@@ -204,6 +209,7 @@ int main(int argc, char *argv[])
{ 0, 0, 0, 0 }
};
+ mainPid = getpid();
mainThread = pthread_self();
opt = getopt_long( argc, argv, optString, longOpts, &longIndex );
@@ -509,10 +515,16 @@ static void dnbd3_handleSignal(int signum)
static void dnbd3_handleSignal2(int signum, siginfo_t *info, void *data UNUSED)
{
- if ( !pthread_equal( pthread_self(), mainThread ) )
- return;
- memcpy( &lastSignal, info, sizeof(siginfo_t) );
- dnbd3_handleSignal( signum );
+ if ( info->si_pid != mainPid ) { // Source is not this process
+ memcpy( &lastSignal, info, sizeof(siginfo_t) ); // Copy signal info
+ if ( info->si_pid != 0 && !pthread_equal( pthread_self(), mainThread ) ) {
+ pthread_kill( mainThread, info->si_signo ); // And relay signal if we're not the main thread
+ }
+ }
+ if ( pthread_equal( pthread_self(), mainThread ) ) {
+ // Signal received by main thread -- handle
+ dnbd3_handleSignal( signum );
+ }
}
uint32_t dnbd3_serverUptime()