Guaranteeing mutex safety with async signals - c

First, I am aware that the mutexes are not considered async-safe normally. This question concerns the use of sigprocmask to make mutexes safe in a multithreaded program with async signals and signal handlers.
I have some code conceptually like the following:
struct { int a, b; } gvars;
void sigfoo_handler(int signo, siginfo_t *info, void *context) {
if(gvars.a == 42 || gvars.b == 13) {
/* run a chained signal handler */
}
}
/* called from normal code */
void update_gvars(int a, int b) {
gvars.a = a;
gvars.b = b;
}
gvars is a global variable which is too large to fit in a single sig_atomic_t. It is updated by normal code and read from the signal handler. The controlled code is a chained signal handler, and so it must run in signal handler context (it may use info or context). Consequently, all accesses to gvars have to be controlled via some sort of synchronization mechanism. Complicating matters, the program is multithreaded, and any thread may receive a SIGFOO.
Question: By combining sigprocmask (or pthread_sigmask) and pthread_mutex_t, is it possible to guarantee synchronization, using code like the following?
struct { int a, b; } gvars;
pthread_mutex_t gvars_mutex;
void sigfoo_handler(int signo, siginfo_t *info, void *context) {
/* Assume SIGFOO's handler does not have NODEFER set, i.e. it is automatically blocked upon entry */
pthread_mutex_lock(&gvars_mutex);
int cond = gvars.a == 42 || gvars.b == 13;
pthread_mutex_unlock(&gvars_mutex);
if(cond) {
/* run a chained signal handler */
}
}
/* called from normal code */
void update_gvars(int a, int b) {
sigset_t set, oset;
sigemptyset(&set);
sigaddset(&set, SIGFOO);
pthread_sigmask(SIG_BLOCK, &set, &oset);
pthread_mutex_lock(&gvars_mutex);
gvars.a = a;
gvars.b = b;
pthread_mutex_unlock(&gvars_mutex);
pthread_sigmask(SIG_SETMASK, &oset, NULL);
}
The logic goes as following: within sigfoo_handler, SIGFOO is blocked so it cannot interrupt the pthread_mutex_lock. Within update_gvars, SIGFOO cannot be raised in the current thread during the pthread_sigmask-protected critical region, and so it can't interrupt the pthread_mutex_lock either. Assuming no other signals (and we can always block any other signals that could be problematic), the lock/unlocks should always proceed in a normal, uninterruptible fashion on the current thread, and the use of lock/unlock should ensure that other threads don't interfere. Am I right, or should I avoid this approach?

I found this paper https://www.cs.purdue.edu/homes/rego/cs543/threads/signals.pdf that discusses running AS-unsafe code in sig handlers safely by
masking out signals in AS-unsafe blocks of normal-context code (explored as less efficient) OR
protecting AS-unsafe blocks of normal-context code with a global sig_atomic volatile flag that prevents the AS-unsafe code in the handler from being entered if set (explored as efficient)
This approach satisfies the part of the POSIX standard that says that
calling AS-unsafe functions in sig-handlers is only deemed unsafe if the sighandler interrupts an AS-unsafe function (http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03_03 : scroll down to the 1st paragraph after the function list)
I think what you're toying with here is essentially a more fine-grained version of this idea, since you're not trying to prevent
pthread_mutex_lock(&gvars_mutex);
int cond = gvars.a == 42 || gvars.b == 13;
pthread_mutex_unlock(&gvars_mutex);
run from a sig-handler from clashing with any AS-unsafe code but rather just with this same/similar AS-unsafe code dealing with this mutex and these variables.
Unfortunately, POSIX only seems to have a code-only concept of signal-safety: a function is either safe or unsafe, regardless of its arguments.
However, IMO, a semaphores/mutex has no good reason to operate on any data or OS handles other than those contained in the mutex/semaphore they're passed, so I think calling sem_wait(&sem)/pthread_mutex_lock(&mx); from a signal handler ought to be safe if it's guaranteed to never clash with a sem_wait/pthread_mutex_lock to the same mutex, even though the POSIX standard technically says it shouldn't be safe (counter-arguments more than welcome).

You obviously know you're into undefined behavior territory with your mention of sig_atomic_t. That being said, the only way I can see this exact example not working on modern unix-like systems is if the signal was set up with SA_NODEFER.
The mutex is enough to ensure proper synchronization between different threads (including the signal handler being run in another thread) and the sigmask will prevent the signal handler in this thread recursing the mutex.
That being said, you're in deep water with locks inside signal handlers. One signal handler might be safe enough, but if you had two signal handlers doing the same trick with different locks you end up with lock ordering deadlocks. This can be somewhat mitigated by applying process sigmasks instead of thread sigmasks. A simple debugging fprintf in the signal handler will definitely violate lock ordering, for example.
I would back away and redesign my application because stuff like this in a signal handler is a sign it's getting too complex and too easy to break. Signal handlers touching one sig_atomic_t are the only defined thing in the C standard because of the exploding complexity of getting anything else right.

Related

how to alternate continously Signal handler

I want to write a program in c for linux that catchs the first SIGUSR1 signal, ignores the second one and continue in this behaviour (catch-ignore) for the successive SIGUSR1 signals.
I wonder how to keep alternating between the two handlers, because once i set the handler to SIG_IGN, the signal will be ignored and I won't be able to detect it and act accordingly.
This is the code i have tried:
int tst;
void sigusr1_handler(){
if(tst==0){
signal(SIGUSR1,SIG_IGN);
tst=1;
}
else tst= 0;
}
int main(){
signal(SIGUSR1, sigusr1_handler);
tst=1;
while(1){}
return 0;
}
You do not.
What you can do, is have your signal handler decide whether to do something or not -- for example, whether to call an another function or not. This is not completely reliable, however, because standard POSIX signals like SIGUSR1 are not queued. If two or more signals are sent at (nearly) the same time, only one is actually delivered. POSIX realtime signals (SIGRTMIN+0 to SIGRTMAX-0 -- from the programmer's point of view, only the number and semantics differ) are queued, but even they can be dropped in some situations.
In all cases, remember that a signal handler function can only use async-signal safe functions. If you need to be able to use all functions, you should instead block the signals in all threads, and have a dedicated thread receive the signals using e.g. sigwaitinfo(). In this case, you don't have signal handler functions, but instead a dedicated thread that receives the signals, and is thus free to use any functions it wants.
If we reword the question into "How do I alternate the handling of a delivered signal in a single-threaded program?", the answer is simple: you use a volatile sig_atomic_t counter.
For alternating between two choices, do_something_odd() first:
#include <signal.h>
void my_signal_handler(int signum)
{
static volatile sig_atomic_t count = 0;
switch (++count) {
case 1:
do_something_odd();
break;
default:
count = 0;
do_something_even();
break;
}
}
For alternating between three cases, you add more case statements as necessary:
#include <signal.h>
void my_signal_handler(int signum)
{
static volatile sig_atomic_t count = 0;
switch (++count) {
case 2:
do_something_2_of_3();
break;
case 1:
do_something_1_of_3();
break;
default:
count = 0;
do_something_3_of_3()
break;
}
}
The above assumes you install the signal handler using sigaction() without SA_SIGINFO in .sa_flags.
The POSIX standard says you can do up to 128 cases (as sig_atomic_t is guaranteed to be able to represent values 0 to 127, inclusive) this way.
You can do larger sets using an unsigned int or unsigned long, but then you must NOT have SA_NODEFER in the .sa_flags, and if the same handler is used for multiple signals, the .sa_mask must have all the other signals handled by the same handler set. This ensures that the signal handler is not interrupted by another signal that is delivered to the same handler, and allows us to use non-atomic counter variable.
In a multithreaded program one must rely on compiler-provided atomic operations, either legacy __sync built-ins, or __atomic built-ins. They are not GCC-specific; at least Intel Compiler Collection and clang provide them also. For alternating between two options, our = __atomic_xor_fetch(&counter, 1, __ATOMIC_SEQ_CST); or our = __sync_xor_and_fetch(&counter, 1); can be used to obtain and flip a counter between 0 and 1 atomically. For a non-power-of-two number of options, a compare-and-swap loop is typically used.

Is there a way to ensure atomicity while having a multithreaded program with signal handlers?

If I have a program like this (in pseudocode):
mutex_lock;
func() {
lock(mutex_lock);
// Some code (long enough to make a
// race condition if no proper synchronisation
// is available). We also going to call a signal,
// say, SIGINT, through (ctrl-c), while we are in
// the range of locking and unlocking the lock.
unlock(mutex_lock);
}
sig_handler_func(sig) {
// Say, we are handling SIGINT (ctrl-c) signal
// And we need to call func from here too.
if (sig == SIGINT) {
func();
}
}
main() {
// Calling func from main
func();
}
then there would be a deadlock when trying to acquire the lock in func, while it is already acquired from the 'main' caller. I was wondering if there is a way to suspend the signal handling in the C language, specifically, when, in this example, entering func and acquiring the lock, and resume the signal handling AND call the handlers upon exiting func.
You want pthread_sigmask, the multithread version of sigprocmask
Here's some sample pseudo code:
int
main(void)
{
sigset_t omask;
sigset_t nmask;
// add as many signals as you want to the mask ...
sigemptyset(&nmask);
sigaddset(&nmask,SIGINT);
// [temporarily] block signals
pthread_sigmask(SIG_BLOCK,&nmask,&omask);
// call function safely
func();
// restore signal mask
pthread_sigmask(SIG_SETMASK,&omask,NULL);
// pending signals should occur now ...
}
I'm not totally sure, but, you may need to use pthread_sigmask to block signals in all but one thread and do the above from that thread only.
Also, I'd be remiss if I didn't say that I'd refactor your code. The number of things you can do in a signal handler [aside from this] is limited (e.g. no malloc, no printf, etc.)
Dedicating one thread for signal handling and having it do sigsetjmp and the signal handler does siglongjmp.
Or have the signal handler set a volatile global (e.g. signal_occurred) that is monitored at base level.
Thus, all the "heavy lifting" that you'd be doing in the signal handler can be done from base task level where you can do anything.
You need two locks. The one used inside your func(), and one to protect the process's signal mask.
You have to make masking and unmasking the signal atomic also:
static pthread_mutex_t mask_mutex = PTHREAD_MUTEX_INITIALIZER;
sigset_t old_set;
sigset_t new_set;
sigemptyset( &new_set );
sigaddset( &new_set, SIGINT );
pthread_mutex_lock( &mask_mutex );
pthread_sigmask( SIG_BLOCK, &new_mask, &old_mask );
func();
pthread_sigmask( SIG_SETMASK, &old_mask, NULL );
pthread_mutex_unlock( &mask_mutex );
With no lock around the pthread_sigmask(), threads are likely to corrupt the process sigmask as execution overlaps.
You may use the test mutex functions (trylock) in this kind of undefined situations, to be safe. And with this, you don't necessarily need to block too.

c setitimer not sending signal when outside its call scope

i have the following case
void foo() {
printf("hi\n");
while(1);
}
int main(void)
{
struct sigaction temp;
temp.sa_handler = &foo;
sigfillset(&temp.sa_mask);
sigdelset(&temp.sa_mask, SIGVTALRM);
sigdelset(&temp.sa_mask, SIGINT );
sigaction(SIGVTALRM, &temp, NULL);
struct itimerval tv;
tv.it_value.tv_sec = 2; /* first time interval, seconds part */
tv.it_value.tv_usec = 0; /* first time interval, microseconds part */
tv.it_interval.tv_sec = 2; /* following time intervals, seconds part */
tv.it_interval.tv_usec = 0; /* following time intervals, microseconds part */
if (setitimer(ITIMER_VIRTUAL, &tv, NULL)){
perror(NULL);
}
while(1);
return 0;
}
all I want is that every 2 seconds foo will be called (foo actually does some other stuff other than while(1), just assume foo run takes more than 2 seconds), after 2 seconds foo is indeed called but then no other call is made untill foo returns. I tried playing with the signal masks (hence the sigfillset) but also when simply calling signal(SIGVTALRM, foo) no changes are made in the result. I also tried having the itimerval and the sigactions variables declared outside main and it didn't quite affect anything.
is the thing I'm trying to do even possible?
thanks!
reference: <http://www.gnu.org/software/libc/manual/html_node/Signals-in-Handler.html>
24.4.4 Signals Arriving While a Handler Runs
What happens if another signal arrives while your signal handler function is running?
When the handler for a particular signal is invoked, that signal is automatically blocked until the handler returns. That means that if two signals of the same kind arrive close together, the second one will be held until the first has been handled. (The handler can explicitly unblock the signal using sigprocmask, if you want to allow more signals of this type to arrive; see Process Signal Mask.)
However, your handler can still be interrupted by delivery of another kind of signal. To avoid this, you can use the sa_mask member of the action structure passed to sigaction to explicitly specify which signals should be blocked while the signal handler runs. These signals are in addition to the signal for which the handler was invoked, and any other signals that are normally blocked by the process. See Blocking for Handler.
When the handler returns, the set of blocked signals is restored to the value it had before the handler ran. So using sigprocmask inside the handler only affects what signals can arrive during the execution of the handler itself, not what signals can arrive once the handler returns.
Portability Note: Always use sigaction to establish a handler for a signal that you expect to receive asynchronously, if you want your program to work properly on System V Unix. On this system, the handling of a signal whose handler was established with signal automatically sets the signal’s action back to SIG_DFL, and the handler must re-establish itself each time it runs. This practice, while inconvenient, does work when signals cannot arrive in succession. However, if another signal can arrive right away, it may arrive before the handler can re-establish itself. Then the second signal would receive the default handling, which could terminate the process.
reference:<http://www.gnu.org/software/libc/manual/html_node/Process-Signal-Mask.html#Process-Signal-Mask>
24.7.3 Process Signal Mask
The collection of signals that are currently blocked is called the signal mask. Each process has its own signal mask. When you create a new process (see Creating a Process), it inherits its parent’s mask. You can block or unblock signals with total flexibility by modifying the signal mask.
The prototype for the sigprocmask function is in signal.h.
Note that you must not use sigprocmask in multi-threaded processes, because each thread has its own signal mask and there is no single process signal mask. According to POSIX, the behavior of sigprocmask in a multi-threaded process is “unspecified”. Instead, use pthread_sigmask.
Function: int sigprocmask (int how, const sigset_t *restrict set, sigset_t *restrict oldset)
Preliminary: | MT-Unsafe race:sigprocmask/bsd(SIG_UNBLOCK) | AS-Unsafe lock/hurd | AC-Unsafe lock/hurd | See POSIX Safety Concepts.
The sigprocmask function is used to examine or change the calling process’s signal mask. The how argument determines how the signal mask is changed, and must be one of the following values:
SIG_BLOCK
Block the signals in set—add them to the existing mask. In other words, the new mask is the union of the existing mask and set.
SIG_UNBLOCK
Unblock the signals in set—remove them from the existing mask.
SIG_SETMASK
Use set for the mask; ignore the previous value of the mask.
The last argument, oldset, is used to return information about the old process signal mask. If you just want to change the mask without looking at it, pass a null pointer as the oldset argument. Similarly, if you want to know what’s in the mask without changing it, pass a null pointer for set (in this case the how argument is not significant). The oldset argument is often used to remember the previous signal mask in order to restore it later. (Since the signal mask is inherited over fork and exec calls, you can’t predict what its contents are when your program starts running.)
If invoking sigprocmask causes any pending signals to be unblocked, at least one of those signals is delivered to the process before sigprocmask returns. The order in which pending signals are delivered is not specified, but you can control the order explicitly by making multiple sigprocmask calls to unblock various signals one at a time.
The sigprocmask function returns 0 if successful, and -1 to indicate an error. The following errno error conditions are defined for this function:
EINVAL
The how argument is invalid.
You can’t block the SIGKILL and SIGSTOP signals, but if the signal set includes these, sigprocmask just ignores them instead of returning an error status.
Remember, too, that blocking program error signals such as SIGFPE leads to undesirable results for signals generated by an actual program error (as opposed to signals sent with raise or kill). This is because your program may be too broken to be able to continue executing to a point where the signal is unblocked again. See Program Error Signals.
I know that this has been answered and accepted already but I made tiny changes to the OP's question as follows in accordance with my comments and had a successful result (foo being called every 2 seconds, ad infinitum)
Note that addition of the memset of the temp variable and the changing from SIGVTALRM to SIGALRM.
#include <stdio.h>
#include <sys/time.h>
void foo() {
printf("hi\n");
}
int main(int argc, char **argv)
{
struct sigaction temp;
memset(&temp, 0, sizeof(temp));
temp.sa_handler = &foo;
sigfillset(&temp.sa_mask);
sigdelset(&temp.sa_mask, SIGALRM);
sigdelset(&temp.sa_mask, SIGINT );
sigaction(SIGALRM, &temp, NULL);
struct itimerval tv;
tv.it_value.tv_sec = 2; /* first time interval, seconds part */
tv.it_value.tv_usec = 0; /* first time interval, microseconds part */
tv.it_interval.tv_sec = 2; /* following time intervals, seconds part */
tv.it_interval.tv_usec = 0; /* following time intervals, microseconds part */
if (setitimer(ITIMER_REAL, &tv, NULL)){
fprintf (stderr, "cannot start timer\n");
perror(NULL);
}
while(1) {
fprintf (stdout, "sleep 1\n");
sleep (1);
}
return 0;
}

signal always ends program

Doing homework with signals and fork and have a problem with the signal.
I've created the function:
void trata_sinal_int() {
char op[2];
printf("\nTerminate? (y/n)\n");
scanf("%s", op);
if (op[0] == 'y') {
printf("Bye Bye\n");
exit(0);
}
}
And in main I have:
signal(SIGINT, trata_sinal_int);
When I run this, and press CTRL ^C the function void trata_sinal_int() is called and I got the message.
If I press y program ends as expected but if I press n program still ends.
It is not returning to were he was before pressing CTRL ^C.
Is this supposed to happen?
It depends on which standard you are adhering to, but Standard C doesn't allow you to do much more than modify a variable of type volatile sig_atomic_t or call _Exit (or abort() or signal()) from a signal handler. POSIX is a lot more lenient. Your code in your signal handler, replete with user interaction, is pushing beyond the limits of what even POSIX allows. Normally, you want your signal handler function to be small and svelte.
Note that the signal handler function should be:
void trata_sinal_int(int signum)
{
This allows you to compile without casts or compiler warnings about type mismatches.
The signal() function may reset the signal handler back to default behaviour when it is invoked; classically, it is necessary to reinstate the signal handler inside the signal handler:
signal(signum, trata_sinal_int);
So far, that's all pretty generic and semi-trivial.
When you type the Control-C, the system does go back to roughly where it was when the signal was originally received. However, what happens next depends on where it was (one of the reasons you have to be so very careful inside the handler). For example, if it was in the middle of manipulating the free list pointers inside malloc(), it would return there, but if you'd reinvoked malloc() inside the handler, all hell might be breaking loose. If you were inside a system call, then your call may be interrupted (return with an error indication and errno == EINTR), or it may resume where it left off. Otherwise, it should go back to where the calculation was running.
Here's (a fixed up version of) your code built into a test rig. The pause() function waits for a signal before returning.
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
static void trata_sinal_int(int signum)
{
char op[2];
signal(signum, trata_sinal_int);
printf("\nTerminate? (y/n)\n");
scanf("%s", op);
if (op[0] == 'y')
{
printf("Bye Bye\n");
exit(0);
}
}
int main(void)
{
signal(SIGINT, trata_sinal_int);
for (int i = 0; i < 3; i++)
{
printf("Pausing\n");
pause();
printf("Continuing\n");
}
printf("Exiting\n");
return(0);
}
I should really point out that the scanf() is not very safe at all; a buffer of size 2 is an open invitation to buffer overflow. I'm also not error checking system calls.
I tested on Mac OS X 10.7.5, a BSD derivative. The chance are good that the resetting of signal() would be unnecessary on this platform, because BSD introduced 'reliable signals' a long time ago (pre-POSIX).
ISO/IEC 9899:2011 §7.14.1.1 The signal function
¶5 If the signal occurs other than as the result of calling the abort or raise function, the
behavior is undefined if the signal handler refers to any object with static or thread
storage duration that is not a lock-free atomic object other than by assigning a value to an
object declared as volatile sig_atomic_t, or the signal handler calls any function
in the standard library other than the abort function, the _Exit function, the
quick_exit function, or the signal function with the first argument equal to the
signal number corresponding to the signal that caused the invocation of the handler.
Furthermore, if such a call to the signal function results in a SIG_ERR return, the
value of errno is indeterminate.252)
252) If any signal is generated by an asynchronous signal handler, the behavior is undefined.
The references to quick_exit() are new in C2011; they were not present in C1999.
POSIX 2008
The section on Signal Concepts goes through what is and is not allowed inside a signal handler under POSIX in considerable detail.
First, your signal handler is not exactly async signal safe. In practice this is probably not a problem in your case, since I assume the main() is basically doing nothing while it is waiting for the signal. But it is definately not correct anyway.
As for why the program exits, not counting segfault:s in the signal handler due to invalid use of FILE* functions such as printf, sscanf etc, when the signal is received any system calls you are doing (or, well, most) will be interreupted with EAGAIN.
If you are using something like sleep() in main to wait for the signal to occur it will be interrupted. You are expected to restart it manually.
To avoid this you probably want to use the significantly more portable sigaction interface instead of signal. If nothing else this allows you to indicate that you want system calls to be restarted.
The reason that FILE * functions (and most other functions that use global state such as malloc and free) is not allowed in signal handlers is that you might be in the middle of another operation on the same state when the signal arrives.
This can cause segfaults or other undefined operations.
The normal 'trick' to implement this is to have a self-pipe: The signal handler will write a byte to the pipe, and your main loop will see this (usually by waiting in poll or something similar) and then act on it.
If you absolutely want to do user interaction in the signal handler you have to use write() and read(), not the FILE* functions.

Signal handler for SIGALRM does not work even if resetting in the handler

The example code of section 10.6, the expected result is:
after several iterations, the static structure used by getpwnam will be corrupted, and the program will terminate with SIGSEGV signal.
But on my platform, Fedora 11, gcc (GCC) 4.4.0, the result is
[Langzi#Freedom apue]$ ./corrupt
in sig_alarm
I can see the output from sig_alarm only once, and the program seems hung up for some reason, but it does exist, and still running.
But when I try to use gdb to run the program, it seems OK, I will see the output from sig_alarm at regular intervals.
And from my manual, it said the signal handler will be set to SIG_DEF after the signal is handled, and system will not block the signal. So at the beginning of my signal handler I reset the signal handler.
Maybe I should use sigaction instead, but I only want to know the reason about the difference between normal running and gdb running.
Any advice and help will be appreciated.
following is my code:
#include "apue.h"
#include <pwd.h>
void sig_alarm(int signo);
int main()
{
struct passwd *pwdptr;
signal(SIGALRM, sig_alarm);
alarm(1);
for(;;) {
if ((pwdptr = getpwnam("Zhijin")) == NULL)
err_sys("getpwnam error");
if (strcmp("Zhijin", pwdptr->pw_name) != 0) {
printf("data corrupted, pw_name: %s\n", pwdptr->pw_name);
}
}
}
void sig_alarm(int signo)
{
signal(SIGALRM, sig_alarm);
struct passwd *rootptr;
printf("in sig_alarm\n");
if ((rootptr = getpwnam("root")) == NULL)
err_sys("getpwnam error");
alarm(1);
}
According to the standard, you're really not allowed to do much in a signal handler. All you are guaranteed to be able to do in the signal-handling function, without causing undefined behavior, is to call signal, and to assign a value to a volatile static object of the type sig_atomic_t.
The first few times I ran this program, on Ubuntu Linux, it looked like your call to alarm in the signal handler didn't work, so the loop in main just kept running after the first alarm. When I tried it later, the program ran the signal handler a few times, and then hung. All this is consistent with undefined behavior: the program fails, sometimes, and in various more or less interesting ways.
It is not uncommon for programs that have undefined behavior to work differently in the debugger. The debugger is a different environment, and your program and data could for example be laid out in memory in a different way, so errors can manifest themselves in a different way, or not at all.
I got the program to work by adding a variable:
volatile sig_atomic_t got_interrupt = 0;
And then I changed your signal handler to this very simple one:
void sig_alarm(int signo) {
got_interrupt = 1;
}
And then I inserted the actual work into the infinite loop in main:
if (got_interrupt) {
got_interrupt = 0;
signal(SIGALRM, sig_alarm);
struct passwd *rootptr;
printf("in sig_alarm\n");
if ((rootptr = getpwnam("root")) == NULL)
perror("getpwnam error");
alarm(1);
}
I think the "apue" you mention is the book "Advanced Programming in the UNIX Environment", which I don't have here, so I don't know if the purpose of this example is to show that you shouldn't mess around with things inside of a signal handler, or just that signals can cause problems by interrupting the normal work of the program.
According to the spec, the function getpwnam is not reentrant and is not guaranteed to be thread safe. Since you are accessing the structure in two different threads of control (signal handlers are effectively running in a different thread context), you are running into this issue. Whenever you have concurrent or parallel execution (as when using pthreads or when using a signal handler), you must be sure not to modify shared state (e.g. the structure owned by 'getpwnam'), and if you do, then appropriate locking/synchronization must be used.
Additionally, the signal function has been deprecated in favor of the sigaction function. In order to ensure portable behavior when registering signal handlers, you should always use the sigaction invocation.
Using the sigaction function, you can use the SA_RESETHAND flag to reset the default handler. You can also use the sigprocmask function to enable/disable the delivery of signals without modifying their handlers.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void sigalrm_handler(int);
int main()
{
signal(SIGALRM, sigalrm_handler);
alarm(3);
while(1)
{
}
return 0;
}
void sigalrm_handler(int sign)
{
printf("I am alive. Catch the sigalrm %d!\n",sign);
alarm(3);
}
For example, my code is runing in main doing nothing and every 3 seconds my program says im alive x)
I think that if you do as i done calling in the handler function alarm with value 3, the problem is resolved :)

Resources