I have 2 threads(thread1 and thread2). And I have signal disposition for SIGINT. Whenever SIGINT occurs thread 2 should handle the signal. For that I wrote below program
void sig_hand(int no) //signal handler
{
printf("handler executing...\n");
getchar();
}
void* thread1(void *arg1) //thread1
{
while(1) {
printf("thread1 active\n");
sleep(1);
}
}
void * thread2(void * arg2) //thread2
{
signal(2, sig_hand);
while(1) {
printf("thread2 active\n");
sleep(3);
}
}
int main()
{
pthread_t t1;
pthread_t t1;
pthread_create(&t1, NULL, thread1, NULL);
pthread_create(&t2, NULL, thread2, NULL);
while(1);
}
I compiled and and run the program. for every 1 second "thread1 active" is printing and for every 3 seconds "thread2 active" is printing.
Now I generated SIGINT. But its printing "thread1 active" and "thread2 active" messages like above. Again I generated SIGINT, now for every 3 seconds only "thread2 active" message is printing. Again I generated SIGINT, now all threads are blocked.
So I understood, for first time main thread executing signal handler. For second time thread1 executing handler and lastly thread2 executing signal handler.
How I can write the code like whenever signal occurs, only thread2 have to execute my signal handler?
If you send a signal to a process, which thread in the process will handle this signal is undetermined.
According to pthread(7):
POSIX.1 also requires that threads share a range of other attributes (i.e., these attributes are process-wide rather than per-thread):
...
- signal dispositions
...
POSIX.1 distinguishes the notions of signals that are directed to the process as a whole and signals that are directed to individual threads. According to POSIX.1, a process-directed signal (sent using kill(2), for example) should be handled by a single, arbitrarily selected thread within the process.
If you want a dedicated thread in your process to handle some signals, here is an example from pthread_sigmask(3) shows you how to do it:
The program below blocks some signals in the main thread, and then creates a dedicated thread to fetch those signals via sigwait(3). The following shell session demonstrates its use:
$ ./a.out &
[1] 5423
$ kill -QUIT %1
Signal handling thread got signal 3
$ kill -USR1 %1
Signal handling thread got signal 10
$ kill -TERM %1
[1]+ Terminated ./a.out
Program source
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
/* Simple error handling functions */
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static void *
sig_thread(void *arg)
{
sigset_t *set = arg;
int s, sig;
for (;;) {
s = sigwait(set, &sig);
if (s != 0)
handle_error_en(s, "sigwait");
printf("Signal handling thread got signal %d\n", sig);
}
}
int
main(int argc, char *argv[])
{
pthread_t thread;
sigset_t set;
int s;
/* Block SIGQUIT and SIGUSR1; other threads created by main()
will inherit a copy of the signal mask. */
sigemptyset(&set);
sigaddset(&set, SIGQUIT);
sigaddset(&set, SIGUSR1);
s = pthread_sigmask(SIG_BLOCK, &set, NULL);
if (s != 0)
handle_error_en(s, "pthread_sigmask");
s = pthread_create(&thread, NULL, &sig_thread, (void *) &set);
if (s != 0)
handle_error_en(s, "pthread_create");
/* Main thread carries on to create other threads and/or do
other work */
pause(); /* Dummy pause so we can test program */
}
Read carefully signal(7) & pthread(7) & pthread_kill(3) & sigprocmask(2) & pthread_sigmask(3) -which you could use (to block SIGINT in unwanted threads). Read also a pthread tutorial.
Avoid using signals to communicate or synchronize between threads. Consider e.g. mutexes (pthread_mutex_lock etc...) and condition variables (pthread_cond_wait etc...).
If one of the threads runs an event loop (e.g. around poll(2)...) consider using signalfd(2).
Related
The POSIX pselect function take a signal mask argument. The signal mask is "atomically" set as the current mask before execution of the function begins, and is restored as the function returns.
This allows an otherwise masked signal to be unmasked while the function executes, and masked again when the function returns. It's guaranteed* that if a signal unmasked in this way is caught, the pselect function will be interrupted by the signal and (unless the signal action is specified with the SA_RESTART flag) will return an EINTR error.
(*: or is it? the language in the document linked above would seem to allow that a signal being received between when pselect unblocked due to seeing a file readiness or timeout and when it replaced the signal mask with the original would not necessarily cause EINTR, since EINTR is required if "The function was interrupted while blocked ..." - however, that ultimately doesn't affect this question).
My question is: supposing that two separate signals are temporarily unmasked during pselect execution, is it possible that both signals will be caught before the pselect function returns and the previous signal mask is restored - or is there some kind of guarantee that only one signal will be caught in this case (leaving the other one pending)? (For purposes of the question, suppose that SA_RESTART is not set for the signal action, and that all signals were specified to be masked during execution of the signal handler when it was established via sigaction).
I can find nothing which suggests that only one signal may be processed, but I may have missed something, and I am writing some code for which this would be a very useful guarantee. I'd be interested to know if POSIX itself makes any guarantee, and also if different OSes provide such a guarantee independently.
No, but it also doesn’t specify that multiple signals can or must. Since it is unspecified, it is best to follow the general rule, which allows all pending unmasked signals to be processed. If you attempt to strictly depend upon this, you are likely on a bad path because the timing of asynchronous events is difficult to predict.
In general, it would be very difficult to make an implementation that imposed an ‘only one' restriction because the os runtime would have to leave one or more signals pending but unmasked until some unspecified point. Remember that the signal handler which runs when pselect is interrupted could do a siglongjmp rather than returning, so the kernel would have to keep a complicated, possibly unbounded data structure to track which signal mask to enforce.
Below is a modified version of your test program. In this one, each event emits a string via write() so there are no buffering problems. The program sets its “main” environment to mask SIGUSR1, SIGUSR2; but while pselect is running, it permits SIGUSR1, SIGUSR2, SIGTERM.
The program forks, with the parent (default:) sitting in a loop invoking pselect(), then outputting ‘.’ after it completes.
The child sits in a loop, delivering SIGUSR1, SIGUSR2 to the parent, then sleeping for a bit. It outputs ‘^’ after delivering the signals.
The handler emits a prefix “(1” or “(2” for SIGUSR1, SIGUSR2 resp; then sleeps for a bit, and outputs “)” to indicate the sleep has completed.
The output I see on macos (10.12.6, but I doubt it matters much) is:
^(2)(1).^(2)(1).^(2)(1).^(2)(1).Terminated: 15
which indicates that the signal handler for each of SIGUSR1 and SIGUSR2 are being run for every invocation of pselect(). This is what I would expect; as it is designed to not admit a window of uncertainty as would be the case with bracketting select() with sigprocmasks().
#include <stdio.h>
#include <signal.h>
#include <sys/select.h>
#include <unistd.h>
void handle(int signo)
{
char s[2];
s[0] = '(';
s[1] = signo == SIGUSR1? '1' : '2';
write(1, s, 2);
sleep(1);
write(1, ")", 1);
}
int main(int argc, char **argv)
{
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
sigaddset(&mask, SIGUSR2);
sigprocmask(SIG_SETMASK, &mask, NULL);
sigfillset(&mask);
sigdelset(&mask, SIGUSR1);
sigdelset(&mask, SIGUSR2);
sigdelset(&mask, SIGTERM);
signal(SIGUSR1, handle);
signal(SIGUSR2, handle);
pid_t t = fork();
switch (t) {
default:
while (1) {
/* no USR1, USR2 */
pselect(0, NULL, NULL, NULL, NULL, &mask);
/* no USR1, USR2 */
write(1, ".", 1);
}
break;
case 0:
t = getppid();
for (int i = 0; i < 4; i++) {
kill(t, SIGUSR1);
kill(t, SIGUSR2);
write(1, "^", 1);
sleep(5);
}
kill(t, SIGTERM);
break;
case -1:
perror("fork\n");
}
return 0;
}
I've continued searching and found no additional information, so I can only conclude that there are no guarantees in POSIX generally.
Under Linux, if I understand the code below correctly, only one signal can be handled (assuming that the signal handler itself doesn't unmask signals): the relevant code and a revealing comment is in fs/select.c, in the do_pselect function:
ret = core_sys_select(n, inp, outp, exp, to);
ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
if (ret == -ERESTARTNOHAND) {
/*
* Don't restore the signal mask yet. Let do_signal() deliver
* the signal on the way back to userspace, before the signal
* mask is restored.
*/
if (sigmask) {
memcpy(¤t->saved_sigmask, &sigsaved,
sizeof(sigsaved));
set_restore_sigmask();
}
} else ...
It essentially returns from the system call, allowing the signal handler to execute, after which the original signal mask will immediately be restored (from current->saved_sigmask, because set_restore_sigmask() sets a flag indicating that this should occur).
The following test program verifies this:
#include <stdio.h>
#include <signal.h>
#include <sys/select.h>
volatile sig_atomic_t got_usr1 = 0;
volatile sig_atomic_t got_usr2 = 0;
void handle_usr1(int signo, siginfo_t *info, void *v)
{
got_usr1 = 1;
}
void handle_usr2(int signo, siginfo_t *info, void *v)
{
got_usr2 = 1;
}
int main(int argc, char **argv)
{
// mask SIGUSR1 and SIGUSR2:
sigset_t curmask;
sigemptyset(&curmask);
sigaddset(&curmask, SIGUSR1);
sigaddset(&curmask, SIGUSR2);
sigprocmask(SIG_SETMASK, &curmask, NULL);
// Create a mask for all but SIGUSR1 and SIGUSR2:
sigset_t mask;
sigfillset(&mask);
sigdelset(&mask, SIGUSR1);
sigdelset(&mask, SIGUSR2);
// Set up signal handlers:
struct sigaction action;
action.sa_sigaction = handle_usr1;
sigfillset(&action.sa_mask);
action.sa_flags = SA_SIGINFO;
sigaction(SIGUSR1, &action, NULL);
action.sa_sigaction = handle_usr2;
sigaction(SIGUSR2, &action, NULL);
// Make signals pending:
raise(SIGUSR1);
raise(SIGUSR2);
// pselect with no file descriptors and no timeout:
pselect(0, NULL, NULL, NULL, NULL, &mask);
int count = got_usr1 + got_usr2;
printf("Handled %d signals while in pselect.\n", count);
return 0;
}
On Linux, the output of the above is consistently:
Handled 1 signals while in pselect.
This also seems to be the case on FreeBSD; however, I'm not willing to count on this being the case on all other platforms. The solution I have found to ensuring that only one signal can be handled is to use siglongjmp to jump out of the signal handler as well as out of the pselect call while also restoring the signal mask so that no further signals can be processed.
Essentially, that code looks like this:
jmp_buf jbuf; // signal handlers have access to this
if (sigsetjmp(jbuf, 1) != 0) {
// We received a signal while in pselect ...
}
int r = pselect(nfds, &read_set_c, &write_set_c, &err_set, wait_ts, &sigmask);
The signal handlers must execute a siglongjmp:
void signal_handler(int signo, siginfo_t *siginfo, void *v)
{
siglongjmp(jbuf, 1);
}
This feels crufty, but seems to work on all platforms that I've tested it on (Linux, MacOS and FreeBSD) - furthermore it seems to be supported by POSIX generally.
I'm trying to build a basic program which has 2/3 threads. The main thread, signaler thread, and receiver thread. I'm trying to make it so the main thread starts both a signaler and receiver thread. The signaler thread is then supposed to send 10 SIGUSR1 signals to the receiver thread and increase a global counter. The receiver thread is supposed to receive the 10 signals while increasing its own counter for each signal received.
The trouble I'm having is with joining the threads back together at the end, specifically joining the receiver thread. The majority of the time the program stalls if I try to join them back together, I assume because the receiver thread hasn't finished its job (maybe it has missed signals?) and so it never finishes. I thought maybe this was the case, so I introduced a wait command in the signaler thread to slow it down, but that didn't change anything.
If I comment out the pthread_join(receiver, NULL) then the program runs, but it only catches one signal most of the time. I assume this is because the receiver thread isn't getting much time to run. (although sometimes it catches various amounts, depending on when it was preempted?)
Leaving the pthread_join(receiver, NULL) in the program makes it stall 19/20 times, but that 1/20 time the program returns 10 signals sent and 10 received. This leads me to believe it has something to do with preemption, but I don't understand why it would ever stall in the first place.
Also right now I just have the receiver thread receiving threads while the received counter is < 10. Ideally I would just want to leave it in while(1) loop, but then again I don't know how to join that back into the main thread without freezing everything.
If someone could help me figure out why signals are being missed / why the program is freezing I would be most grateful. I have a suspicion that I'm not setting up the signal mask correctly for the receiver, but I don't know how else I am supposed to do it. Here is the code:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <signal.h>
void *receivetest(void *args);
void *signaltest(void *args);
int received = 0;
int sent = 0;
pthread_t signaler;
pthread_t receiver;
sigset_t mask;
int main(){
//setting up the signal mask
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
//creation of both threads
pthread_create(&receiver, NULL, receivetest, NULL);
pthread_create(&signaler, NULL, signaltest, NULL);
pthread_join(signaler, NULL);
pthread_join(receiver, NULL);
//printing results after joining them back
printf("I'm the main function\n");
printf("Receieved: %d, sent: %d\n", received, sent);
}
void *signaltest(void *args){
int i = 0;
for(i=0;i<10;i++){ //sends 10 signals to receiver thread
pthread_kill(receiver, SIGUSR1);
sent++;
}
}
void *receivetest(void *args){
int c; //sigwait needs int
pthread_sigmask(SIG_BLOCK, &mask, NULL); //sets up the signal mask for this thread
while(received < 10){ //waits for 10 signals and increments receieved
sigwait(&mask, &c);
received++;
}
}
Signals just don't work that way. If a thread receives a signal while that same signal is already pending, nothing happens. Please use an appropriate inter-thread communication method, not signals.
You almost got it right. It is recommended to block the signals from the main thread to protect all new threads from mishandling the signal.
Any thread created after pthread_sigmask(), inherits the sigmask. The first parameter tells pthread_sigmask() what to do with the signals listed in the second parameter.
This line pthread_sigmask(SIG_BLOCK, &mask, NULL) should be placed in the main thread, not on the signal handler. Your original code will work too, but if the signal is sent to the wrong thread, it will kill the whole process.
In addition, the sender is sending signal faster than the receiver can handle. By sleeping for 1 second between each iteration, the receiver will be able to catch up.
I took the liberty and modified your code. I added some prints within the sender and receiver so you'll know what it is doing.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void receivetest(void); //function does not return anything
void signaltest(void); // does not accept parameter either.
int received = 0;
int sent = 0;
pthread_t signaler;
pthread_t receiver;
sigset_t mask;
int main(){
//setting up the signal mask
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
pthread_sigmask(SIG_BLOCK, &mask, NULL); //sets up the signal mask for this thread
//creation of both threads
pthread_create(&receiver, NULL, (void *)receivetest, NULL);
pthread_create(&signaler, NULL, (void *)signaltest, NULL);
pthread_join(signaler, NULL);
pthread_join(receiver, NULL);
//printing results after joining them back
printf("I'm the main function\n");
printf("Receieved: %d, sent: %d\n", received, sent);
return 0;
}
void signaltest(void){
int i = 0;
for(i=0;i<10;i++){ //sends 10 signals to receiver thread
printf("Sending signal\n");
pthread_kill(receiver, SIGUSR1);
sleep(1); // Don't send signals too fast
sent++;
}
}
void receivetest(void){
int c; //sigwait needs int
while(received < 10){ //waits for 10 signals and increments receieved
sigwait(&mask, &c);
printf("Signal received\n");
received++;
}
}
Output:
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
Sending signal
Signal received
I'm the main function
Receieved: 10, sent: 10
This program is supposed to
The parent simply waits indefinitely for any child to return (hint, waitpid).
b. The child sets up two signal handlers (hint, signal) and goes to sleep for 5 minutes.
i. The first signal handler listens for the USR1 signal, and upon receiving it:
1. Creates a thread (hint, pthread_create).
a. Basically, all that the thread needs to do is “say hello” and sleep for 60
seconds.
ii. The second signal handler listens for the USR2 signal, and upon receiving it:
1. Destroys the thread (hint, pthread_destroy).
My code compiles fine, just when I run it, absolutely nothing happens, not even the first printf which I put there as a test. Ive been staring at it for an hour and there are no errors, so why wont this run?
EDIT: This runs now, thanks charlie, however when it creates the thread, it outputs "[thread] sleeping for 1 m[thread] sleeping for 1 minute" and then ends, it never waits for the 2nd signal
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
pthread_t thread;
void* temp()
{
printf("[thread] hello professor\n");
printf("[thread] sleeping for 1 minute\n");
sleep(60);
}
void handle_USR1(int x)
{
int s;
printf("[signal] creating the thread\n");
s = pthread_create(&thread, NULL, &temp, NULL);
}
void handle_USR2(int x)
{
int s;
printf("[signal] destroying the thread\n");
s = pthread_cancel(thread);
}
int main(void)
{
int status = 0;
if(fork() != 0)
{
printf("[parent] waiting.....\n");
waitpid(-1, &status, 0);
}
else
{
printf("[child] to create the thread: kill -USR1 %d\n", getpid());
printf("[child] to end the thread: kill -USR2 %d\n", getpid());
printf("[child] setting up signal handlers\n");
signal(SIGUSR1, handle_USR1);
signal(SIGUSR2, handle_USR2);
printf("[child] waiting for signals\n");
sleep(300);
}
return (0);
}
Add a newline "\n" to all your printf's. Without it, stdout will not flush and it will appear your program is not working even though it is.
Also, checking fork() for failure is a good idea. fork() returns -1 on failure and sets errno.
I landed on this question while searching something else and realized your program would terminate as soon as SIGUSR1 signal is processed. You need to wait for your thread like you're waiting for child process by issuing pthread_join
void handle_USR1(int x)
{
int s;
printf("[signal] creating the thread\n");
s = pthread_create(&thread, NULL, &temp, NULL);
pthread_join(thread, NULL);
}
I have a thread in an application that has a loop like this:
...
while (1)
{
checkDatabase();
checkChildren();
sleep(3);
}
...
checkDatabase() is self-explanatory; checkChildren() simply calls waitpid(-1, &status, WNOHANG) to deal with child processes that have either exited or received a signal.
The application works fairly well, but it has default signal handling. The problem is that this parent process has a number of threads (don't worry about child processes for now) and I don't have any experience with synchronous signals, let alone in a POSIX threads application. I have used signal() before but apparently it's non-portable and it doesn't do what I need anyway. I have no experience at all with sigaction methods, and I can't find good documentation on how to fill in the structs and so on.
What I need to do is to synchronously catch terminating signals like SIGINT, SIGTERM and SIGQUIT in the above loop (and I need to ignore SIGPIPE altogether so that I can catch the EPIPE error from IO methods), so it would look like this:
...
while (1)
{
checkDatabase();
checkChildren();
checkForSignals();
sleep(3);
}
...
All other threads should not have anything to do with the signal; only the thread that executes this loop should be aware of it. And, obviously, it needs to be a non-blocking check so the loop doesn't block during its first iteration. The method called if a signal is found will sort out the other threads and destroy mutexes, and all that.
Could anyone please give me a heads-up? Many thanks.
(Following the question's comments, and for completeness, this solution tries to avoid signal handlers.)
It is possible to block signals from being raised through sigprocmask() (or, rather, pthread_sigmask() since you're using threads). From there on, the signals that were raised but blocked are available through sigpending().
Therefore, you could do something like (error checking omitted for brevity):
sigset_t blocked;
sigemptyset(&blocked);
sigaddset(&blocked, SIGINT);
sigaddset(&blocked, SIGTERM);
sigaddset(&blocked, SIGQUIT);
pthread_sigmask(SIG_BLOCK, &blocked, NULL); // Block SIGINT, SIGTERM and SIGQUIT.
signal(SIGPIPE, SIG_IGN); // Ignore SIGPIPE.
Then, later:
void checkForSignals(void)
{
sigset_t pending;
sigpending(&pending);
if (sigismember(&pending, SIGINT)) {
// Handle SIGINT...
}
if (sigismember(&pending, SIGTERM)) {
// Handle SIGTERM...
}
if (sigismember(&pending, SIGQUIT)) {
// Handle SIGQUIT...
}
}
Since sigpending() does not block, this seems to match your requirements.
Create a signal handler for SIGINT, SIGTERM and SIGQUIT, using the same function. In that signal function just set a flag that can be polled in your loop.
Something like this:
/* Global variable, will be set to non-zero if SIGINT, SIGTERM or SIGQUIT is caught */
int term_signal_set = 0;
void my_signal_handler(int)
{
term_signal_set = 1;
}
/* ... */
signal(SIGINT, my_signal_handler);
signal(SIGTERM, my_signal_handler);
signal(SIGQUIT, my_signal_handler);
signal(SIGPIPE, SIG_IGN); /* So functions return EPIPE */
while (1)
{
/* ... */
if (term_signal_set > 0)
break; /* Or do something else */
sleep(3);
}
In a multithreaded application receiving a signal, there is no predetermination, which thread receives the signal. Typical workaraounds include setting a global variable in the signal handler and checking it from a dedicated thread.
So in your case the signal handler (called from whatever thread) would just set something like a global variable for the signal received, and in CheckForSignals() you would test it.
sigaction is the way to go. man sigaction should help you. Here is an example from the web
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
struct sigaction act;
void sighandler(int signum, siginfo_t *info, void *ptr)
{
printf("Received signal %d\n", signum);
printf("Signal originates from process %lu\n",
(unsigned long)info->si_pid);
}
int main()
{
printf("I am %lu\n", (unsigned long)getpid());
memset(&act, 0, sizeof(act));
act.sa_sigaction = sighandler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &act, NULL);
// Waiting for CTRL+C...
sleep(100);
return 0;
}
I have a main application that spawns a seperate thread to process messages off a queue. I have an issue on AIX when I hit CTRL-C as it seems to make some "connection handles" in the thread become invalid. I do have a shutdown hook in the main program catching the SIGINT but on AIX it seems to somehow send a signal to the thread as well...although that is not really possible from what I hear...
Essentially I would like to know if I want the MAIN application to handle ALL signals I am interested in and have the thread/s NEVER handle any signals...is that "good practice"?
If so how can I NOT use "sigwait" in the thread...in fact I do not want any "signal code" in the thread/s...they must simply not receive any signals at all.
I have emptied out all the signals:
sigemptyset(&set);
And have set the SIG_BLOCK
s = pthread_sigmask(SIG_BLOCK, &set, NULL);
So here is a dummy test programe:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#define handle_error_en(en, msg) do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static void * threadMainLoop(){
//Here I do not want the thread to use "sigwait"....
while(running == TRUE){
//do some thread work and never have any signals come in
}
}
void shutdownHook(int sig){
printf("\nCtrl-C pressed....shutdown hook in main...\n");
}
void signalErrorHandler(int signum){
printf("\nSignal error handler in main...\n");
}
int main(int argc, char *argv[]){
pthread_t thread;
sigset_t set;
int s;
//Catch the following signals in the MAIN thread
(void) signal(SIGINT, shutdownHook);
(void) signal(SIGSEGV, signalErrorHandler);
(void) signal(SIGBUS, signalErrorHandler);
(void) signal(SIGILL, signalErrorHandler);
(void) signal(SIGTERM, signalErrorHandler);
(void) signal(SIGABRT, signalErrorHandler);
sigemptyset(&set); //BLOCK all signals
s = pthread_sigmask(SIG_BLOCK, &set, NULL);
if (s != 0)
handle_error_en(s, "pthread_sigmask");
s = pthread_create(&thread, NULL, &threadMainLoop, (void *) NULL);
if (s != 0)
handle_error_en(s, "pthread_create");
pause();
}
If I just create a thread and have, for example, the SIGINT signal handler in the MAIN thread but do NOT has the SIG_BLOCK set for the thread and the user hits CTRL-C....does the thread get affected at all even though the signal handler in the main thread runs? That seems to be what I am seeing on AIX ;-(
Thanks for the help, much appreciated
Lynton
With s = pthread_sigmask(SIG_BLOCK, &set, NULL); , you're not blocking anything.
Use:
sigfillset(&set);
sets = pthread_sigmask(SIG_SETMASK, &set, NULL);
If you want to block every signal, or explicitly add the signals you want to block to the set if you're using SIG_BLOCK.
After you've created the threads, you need to restore the signal mask, otherwise no threads will catch any signal.
However, looking at your previous question, it might be that the thread catching the signal doesn't handle being interrupted. That is, if you're blocked doing a syscall, and a signal arrives, that syscall gets aborted. Some operating systems defaults to automatically call the system call again, some returns an error and sets errno to EINTR, which the application must handle - and bad things might happen if that's not handled.
Instead, install your signal handlers with sigaction() instead of signal() , and set the SA_RESTART flag, which will cause system calls to automatically restart in case it got aborted by a signal.
Still wrong design.
Do not use CTRL+C to stop an application in a controlled manner.
Use a correctly designed controller app that will be accessible over CORBA, RMI, or some other method to interact with the user and control the background app.
Have fun guys...