Fix interrupt handling
This commit is contained in:
		
							parent
							
								
									951357e5fb
								
							
						
					
					
						commit
						83ae6503e8
					
				
					 4 changed files with 41 additions and 13 deletions
				
			
		|  | @ -97,6 +97,9 @@ static void opensslLockCallback(int mode, int type, const char * file, int line) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | static void sigHandler(int signo) { } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| void initNix() | void initNix() | ||||||
| { | { | ||||||
|     /* Turn on buffering for cerr. */ |     /* Turn on buffering for cerr. */ | ||||||
|  | @ -130,6 +133,10 @@ void initNix() | ||||||
|     if (sigaction(SIGCHLD, &act, 0)) |     if (sigaction(SIGCHLD, &act, 0)) | ||||||
|         throw SysError("resetting SIGCHLD"); |         throw SysError("resetting SIGCHLD"); | ||||||
| 
 | 
 | ||||||
|  |     /* Install a dummy SIGUSR1 handler for use with pthread_kill(). */ | ||||||
|  |     act.sa_handler = sigHandler; | ||||||
|  |     if (sigaction(SIGUSR1, &act, 0)) throw SysError("handling SIGUSR1"); | ||||||
|  | 
 | ||||||
|     /* Register a SIGSEGV handler to detect stack overflows. */ |     /* Register a SIGSEGV handler to detect stack overflows. */ | ||||||
|     detectStackOverflow(); |     detectStackOverflow(); | ||||||
| 
 | 
 | ||||||
|  | @ -253,6 +260,8 @@ void showManPage(const string & name) | ||||||
| 
 | 
 | ||||||
| int handleExceptions(const string & programName, std::function<void()> fun) | int handleExceptions(const string & programName, std::function<void()> fun) | ||||||
| { | { | ||||||
|  |     ReceiveInterrupts receiveInterrupts; // FIXME: need better place for this
 | ||||||
|  | 
 | ||||||
|     string error = ANSI_RED "error:" ANSI_NORMAL " "; |     string error = ANSI_RED "error:" ANSI_NORMAL " "; | ||||||
|     try { |     try { | ||||||
|         try { |         try { | ||||||
|  |  | ||||||
|  | @ -27,8 +27,7 @@ public: | ||||||
|             fds[0].events = 0; |             fds[0].events = 0; | ||||||
|             if (poll(fds, 1, -1) == -1) abort(); // can't happen
 |             if (poll(fds, 1, -1) == -1) abort(); // can't happen
 | ||||||
|             assert(fds[0].revents & POLLHUP); |             assert(fds[0].revents & POLLHUP); | ||||||
|             /* We got POLLHUP, so send an INT signal to the main thread. */ |             triggerInterrupt(); | ||||||
|             kill(getpid(), SIGINT); |  | ||||||
|         }); |         }); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1197,18 +1197,22 @@ static void signalHandlerThread(sigset_t set) | ||||||
|         int signal = 0; |         int signal = 0; | ||||||
|         sigwait(&set, &signal); |         sigwait(&set, &signal); | ||||||
| 
 | 
 | ||||||
|         if (signal == SIGINT || signal == SIGTERM || signal == SIGHUP) { |         if (signal == SIGINT || signal == SIGTERM || signal == SIGHUP) | ||||||
|             _isInterrupted = 1; |             triggerInterrupt(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|             { | void triggerInterrupt() | ||||||
|                 auto interruptCallbacks(_interruptCallbacks.lock()); | { | ||||||
|                 for (auto & callback : *interruptCallbacks) { |     _isInterrupted = 1; | ||||||
|                     try { | 
 | ||||||
|                         callback(); |     { | ||||||
|                     } catch (...) { |         auto interruptCallbacks(_interruptCallbacks.lock()); | ||||||
|                         ignoreException(); |         for (auto & callback : *interruptCallbacks) { | ||||||
|                     } |             try { | ||||||
|                 } |                 callback(); | ||||||
|  |             } catch (...) { | ||||||
|  |                 ignoreException(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -433,5 +433,21 @@ struct InterruptCallback | ||||||
| std::unique_ptr<InterruptCallback> createInterruptCallback( | std::unique_ptr<InterruptCallback> createInterruptCallback( | ||||||
|     std::function<void()> callback); |     std::function<void()> callback); | ||||||
| 
 | 
 | ||||||
|  | void triggerInterrupt(); | ||||||
|  | 
 | ||||||
|  | /* A RAII class that causes the current thread to receive SIGUSR1 when
 | ||||||
|  |    the signal handler thread receives SIGINT. That is, this allows | ||||||
|  |    SIGINT to be multiplexed to multiple threads. */ | ||||||
|  | struct ReceiveInterrupts | ||||||
|  | { | ||||||
|  |     pthread_t target; | ||||||
|  |     std::unique_ptr<InterruptCallback> callback; | ||||||
|  | 
 | ||||||
|  |     ReceiveInterrupts() | ||||||
|  |         : target(pthread_self()) | ||||||
|  |         , callback(createInterruptCallback([&]() { pthread_kill(target, SIGUSR1); })) | ||||||
|  |     { } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue