Sponsored Content
Full Discussion: Multiple Signals
Top Forums Programming Multiple Signals Post 34060 by Perderabo on Saturday 1st of February 2003 05:46:20 PM
Old 02-01-2003
Hmmm... there seems to be two very different questions here. For your first question about how to write a signal handler that will interrupt itself, the code that I posted really will work provided that you let the prinf finish prior to sending another signal. If this isn't working for you then you not timing the signals correctly. So let's just automate the procedure with a child process that will send the signals with correct timing:
Code:
#include <stdio.h>
#include <signal.h>
void callme ( int sign )
{
        printf ( "Called \n" ) ;
        sleep ( 5 ) ;
        printf("Finished sleeping \n");
}
main ( )
{
        sigset_t mask ;
        struct sigaction action ;
        if(fork()) {
                sigemptyset( &mask ) ;
                setvbuf(stdout, NULL, _IONBF, 0);
                action.sa_mask = mask ;
                action.sa_flags = SA_NODEFER ;
                action.sa_handler = callme ;
                sigaction ( SIGUSR1 , &action , NULL ) ;
                while ( 1 ) ;
        } else {
                sleep(1);
                kill(getppid(), SIGUSR1);
                sleep(1);
                kill(getppid(), SIGUSR1);
                sleep(1);
                kill(getppid(), SIGUSR1);
                sleep(30);
                kill(getppid(), SIGTERM);
                exit(0);
        }
 }

I just can't believe that this will fail on any unix system. You should see:
Called
Called
Called
Finished sleeping
Finished sleeping
Finished sleeping
Terminated

The handler is not simply being called three times. It is really interrupting itself. I don't see how you can prove that it is interrupting itself without a second printf or allowing the first printf to output a few charaters then get interrupted by a second call to printf. printf is not prepared to be interupted by a second call to itself. At best you might see:
CaCaCalled
but I don't see any chance of that unless you completely unbuffer and even then it's dicey. It really depends on how it was written. The best move is to allow printf to finish before sending a second signal.

At some point a second question has been introduced here about sending a lot of signals to a process in a very short time. If a signal is generated more than once before it is delivered to a process, that is too bad. Only one signal will be delivered. Is that why you don't want to defer a signal? Yes, that will help reduce the chance of it happening but there is no complete solution to this problem. Suppose that your process is sitting on a run queue waiting for a cpu. If another process that does have a cpu sends it 5 copies of the same signal, what can the kernel do? When the process runs, it will get one signal.

Since you mention SIGCHLD specificly, this happens to init 100's of times each day. Several children exit, but init only gets one signal. init simply wait()'s in a loop until a wait() fails with ECHILD. If you treat SIGCHLD to mean that zero or more zombies need to reaped, the problem sort of goes away.
 

10 More Discussions You Might Find Interesting

1. Programming

Signals In HP-UX

does the way of handling, interrupting signals in HP-UX same as that of solaris. If there is difference than what it is.?:confused: (1 Reply)
Discussion started by: kapilv
1 Replies

2. Programming

Threads Signals

Hi In my process there are few threads. Now, lets say all the threads are blocked for some reason or other.. now i read it somewhere that the kernel in this situation sends in some signal which can be caught. please let me know what signal is it and more details about that.. Thanks in... (1 Reply)
Discussion started by: uday_kumar_spl
1 Replies

3. UNIX for Dummies Questions & Answers

Signals...

(posted this in the scripting forum as well, but figured it should go here) So, what's going on is this: For our program, we had to create our own shell, and if the user pressed ctrl-c just at the cmdline, then this signal would be ignored, but if there is a foreground process running, let's... (0 Replies)
Discussion started by: blind melon
0 Replies

4. Programming

Using Signals

How can use signals in a C program If i want a child program to signal it's parent program that it(child) program has completed the task that it was assigned.:confused: (2 Replies)
Discussion started by: kapilv
2 Replies

5. UNIX for Dummies Questions & Answers

threads and signals

can any one give me an example of a concurrency program in threads and signals, i.e how to deliver messages between threads using signals. thanks (0 Replies)
Discussion started by: moe_7
0 Replies

6. Programming

threads and signals

can any one give me an example of a concurrency program in threads and signals, i.e how to deliver messages between threads using signals. thanks (2 Replies)
Discussion started by: moe_7
2 Replies

7. OS X (Apple)

How to debug signals

Hi, In our program, we are using SIGTERM and i tired to put break point in this function. But my debuger is unable to brake at that point. I am working on Mac X and using XCode. Thanks (0 Replies)
Discussion started by: Saurabh78
0 Replies

8. Programming

Can we debug Signals

Hi, In our program, we are using SIGTERM and i tired to put break point in this function. But my debuger is unable to brake at that point. I am working on Mac X and using XCode. Thanks (1 Reply)
Discussion started by: Saurabh78
1 Replies

9. Programming

C++ signals Linux

how can do this programs in c++ Program description: Infinite loop in a program starts working with 2 seconds the screen (console) "I 'm trying" to write, but it automatically after 10 seconds, the screen "Close" will terminate the execution of typing. c++ code (3 Replies)
Discussion started by: ss54
3 Replies

10. UNIX for Advanced & Expert Users

Help with Signals

Hi All, The problem statement is as below: Problem: A process (exe) is getting executed in background. The output of this process is getting logged in a file. After successfully running for some time the process gets terminated. In the log file following is present: ^M[7m Interrupt ^M[27m... (8 Replies)
Discussion started by: Praty.27
8 Replies
thr_sigsetmask(3C)														thr_sigsetmask(3C)

NAME
thr_sigsetmask - change or examine calling thread's signal mask SYNOPSIS
cc -mt [ flag... ] file... [ library... ] #include <thread.h> #include <signal.h> int thr_sigsetmask(int how, const sigset_t *set, sigset_t *oset); The thr_sigsetmask() function changes or examines a calling thread's signal mask. Each thread has its own signal mask. A new thread inher- its the calling thread's signal mask and priority; however, pending signals are not inherited. Signals pending for a new thread will be empty. If the value of the argument set is not NULL, set points to a set of signals that can modify the currently blocked set. If the value of set is NULL, the value of how is insignificant and the thread's signal mask is unmodified; thus, thr_sigsetmask() can be used to inquire about the currently blocked signals. The value of the argument how specifies the method in which the set is changed and takes one of the following values: SIG_BLOCK set corresponds to a set of signals to block. They are added to the current signal mask. SIG_UNBLOCK set corresponds to a set of signals to unblock. These signals are deleted from the current signal mask. SIG_SETMASK set corresponds to the new signal mask. The current signal mask is replaced by set. If the value of oset is not NULL, it points to the location where the previous signal mask is stored. Upon successful completion, the thr_sigsetmask() function returns 0. Otherwise, it returns a non-zero value. The thr_sigsetmask() function will fail if: EINVAL The value of how is not defined and oset is NULL. Example 1: Create a default thread that can serve as a signal catcher/handler with its own signal mask. The following example shows how to create a default thread that can serve as a signal catcher/handler with its own signal mask. new will have a different value from the creator's signal mask. As POSIX threads and Solaris threads are fully compatible even within the same process, this example uses pthread_create(3C) if you exe- cute a.out 0, or thr_create(3C) if you execute a.out 1. In this example: o The sigemptyset(3C) function initializes a null signal set, new. The sigaddset(3C) function packs the signal, SIGINT, into that new set. o Either pthread_sigmask() or thr_sigsetmask() is used to mask the signal, SIGINT (CTRL-C), from the calling thread, which is main(). The signal is masked to guarantee that only the new thread will receive this signal. o pthread_create() or thr_create() creates the signal-handling thread. o Using pthread_join(3C) or thr_join(3C), main() then waits for the termination of that signal-handling thread, whose ID number is user_threadID. Then main() will sleep(3C) for 2 seconds, after which the program terminates. o The signal-handling thread, handler: o Assigns the handler interrupt() to handle the signal SIGINT by the call to sigaction(2). o Resets its own signal set to not block the signal, SIGINT. o Sleeps for 8 seconds to allow time for the user to deliver the signal SIGINT by pressing the CTRL-C. /* cc thisfile.c -lthread -lpthread */ #define _REENTRANT /* basic first 3-lines for threads */ #include <pthread.h> #include <thread.h> thread_t user_threadID; sigset_t new; void *handler(), interrupt(); int main( int argc, char *argv[] ){ test_argv(argv[1]); sigemptyset(&new); sigaddset(&new, SIGINT); switch(*argv[1]) { case '0': /* POSIX */ pthread_sigmask(SIG_BLOCK, &new, NULL); pthread_create(&user_threadID, NULL, handler, argv[1]); pthread_join(user_threadID, NULL); break; case '1': /* Solaris */ thr_sigsetmask(SIG_BLOCK, &new, NULL); thr_create(NULL, 0, handler, argv[1], 0, &user_threadID); thr_join(user_threadID, NULL, NULL); break; } /* switch */ printf("thread handler, # %d, has exited ",user_threadID); sleep(2); printf("main thread, # %d is done ", thr_self()); return(0) } /* end main */ struct sigaction act; void * handler(char *argv1) { act.sa_handler = interrupt; sigaction(SIGINT, &act, NULL); switch(*argv1){ case '0': /* POSIX */ pthread_sigmask(SIG_UNBLOCK, &new, NULL); break; case '1': /* Solaris */ thr_sigsetmask(SIG_UNBLOCK, &new, NULL); break; } printf(" Press CTRL-C to deliver SIGINT signal to the process "); sleep(8); /* give user time to hit CTRL-C */ return (NULL) } void interrupt(int sig) { printf("thread %d caught signal %d ", thr_self(), sig); } void test_argv(char argv1[]) { if(argv1 == NULL) { printf("use 0 as arg1 to use thr_create(); or use 1 as arg1 to use pthread_create() "); exit(NULL); } } In the last example, the handler thread served as a signal-handler while also taking care of activity of its own (in this case, sleeping, although it could have been some other activity). A thread could be completely dedicated to signal-handling simply by waiting for the delivery of a selected signal by blocking with sigwait(2). The two subroutines in the previous example, handler() and interrupt(), could have been replaced with the following routine: void * handler(void *ignore) { int signal; printf("thread %d waiting for you to press the CTRL-C keys ", thr_self()); sigwait(&new, &signal); printf("thread %d has received the signal %d ", thr_self(), signal); } /*pthread_create() and thr_create() would use NULL instead of argv[1] for the arg passed to handler() */ In this routine, one thread is dedicated to catching and handling the signal specified by the set new, which allows main() and all of its other sub-threads, created after pthread_sigmask() or thr_sigsetmask() masked that signal, to continue uninterrupted. Any use of sig- wait(2) should be such that all threads block the signals passed to sigwait(2) at all times. Only the thread that calls sigwait() will get the signals. The call to sigwait(2) takes two arguments. For this type of background dedicated signal-handling routine, a Solaris daemon thread can be used by passing the argument THR_DAEMON to thr_create(). See attributes(5) for descriptions of the following attributes: +-----------------------------+------------------------------+ | ATTRIBUTE TYPE | ATTRIBUTE VALUE | +-----------------------------+------------------------------+ |MT-Level |MT-Safe and Async-Signal-Safe | +-----------------------------+------------------------------+ sigaction(2), sigprocmask(2), sigwait(2), cond_wait(3C), pthread_cancel(3C), pthread_create(3C), pthread_join(3C), pthread_self(3C), sigaddset(3C), sigemptyset(3C), sigsetops(3C), sleep(3C), attributes(5), cancellation(5), standards(5) It is not possible to block signals that cannot be caught or ignored (see sigaction(2)). It is also not possible to block or unblock SIG- CANCEL, as SIGCANCEL is reserved for the implementation of POSIX thread cancellation (see pthread_cancel(3C) and cancellation(5)). This restriction is quietly enforced by the standard C library. Using sigwait(2) in a dedicated thread allows asynchronously generated signals to be managed synchronously; however, sigwait(2) should never be used to manage synchronously generated signals. Synchronously generated signals are exceptions that are generated by a thread and are directed at the thread causing the exception. Since sigwait() blocks waiting for signals, the blocking thread cannot receive a synchronously generated signal. Calling thesigprocmask(2) function will be the same as if thr_sigsetmask() or pthread_sigmask() has been called. POSIX leaves the seman- tics of the call to sigprocmask(2) unspecified in a multi-threaded process, so programs that care about POSIX portability should not depend on this semantic. If a signal is delivered while a thread is waiting on a condition variable, the cond_wait(3C) function will be interrupted and the handler will be executed. The state of the lock protecting the condition variable is undefined while the thread is executing the signal handler. Signals that are generated synchronously should not be masked. If such a signal is blocked and delivered, the receiving process is killed. 23 Mar 2005 thr_sigsetmask(3C)
All times are GMT -4. The time now is 11:06 PM.
Unix & Linux Forums Content Copyright 1993-2022. All Rights Reserved.
Privacy Policy