Handling multiple signals - c

I have a question about handling a signal.
Assume that if we recieve SIGINT signal, we should print "Recieved Signal". If within ten seconds the handler recieves another signal, it should print "Shutting Down" then exit with status 1.
I made my code like this:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void handler(int);
void secondhandler(int);
void alrmhandler(int);
void alrmhandler (int alrmsig)
{
alarm(0);
}
void secondhandler(int sig)
{
/* after recieving second signal prints shutting down and exit */
printf("Shutting Down\n");
exit(1);
}
void handler ( int sig )
{
/* recieve first SIGINT signal */
printf ("Recieved Signal\n");
/* handle for the alarm function */
signal(SIGALRM, alrmhandler);
/* start 10s alarm */
alarm(10);
/* catch second SIGINT signal within 10s*/
signal(SIGINT, secondhandler);
}
int main( void )
{
signal(SIGINT, handler);
printf( "Hello World!\n" );
for ( ;; )
{
/* infinite loop */
}
return 0;
}
I tried to compile it with dev c++, but it failed. Because SIGALRM undeclared(first use in this function).
Anyway, what I want to know is if this code is right. I actually kinda not sure with the alrmhandler(). should I ignore the SIGALRM?

If you are on a Windows platform, the only signals you will be able to send are : SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, or SIGTERM.

You write:
what I want to know is if this code is right.
Not entirely. printf() is not async-signal-safe, and so should not be called from within a signal handler unless you are very sure it is safe to do so. It is not safe to do so within the code you provide.
The alarm() technique is, generally, race-prone. Your ten second alarm might expire in the middle of your secondhandler() function. To guard against this, you might mask out signals to compensate with a more sophisticated signal manipulation function.
There are more elegant/flexible ways of implementing the timeout you desire, but that's perhaps a question better suited for codereview.stackexchange.com.

Related

Block SIGINT from terminating program

I need some help on C program - it is a reverse shell (https://github.com/arturgontijo/remoteShell/blob/master/reverseShell.c) I made few changes, like put that all in a loop and some sleep pattern + put some argument to pass directly IP and PORT now that thing works very good it's stable (problem that cannot autocomplete stuff with TAB I don't really care) BUT what I really care is that this thing will break if on target machine I press CTRL+C the program just exits itself. Now I used this example to block CTRL+C calls:
/* Signal Handler for SIGINT */
void sigintHandler(int sig_num)
{
/* Reset handler to catch SIGINT next time.
Refer http://en.cppreference.com/w/c/program/signal */
signal(SIGINT, sigintHandler);
printf("\n Cannot be terminated using Ctrl+C \n");
fflush(stdout);
}
signal(SIGINT, sigintHandler);
I got this example online and put it on my loop as well, but still from client pressing ctrl+C breaks program. I wonder dup2() is responsible for that or something because on simple C program this actually worked fine.
You can use the sigetops family of functions to manipulate the signals sent into your application.
So for your example you could use:
#include <signal.h>
#include <unistd.h>
int main(int argc, char **argv)
{
sigset_t block_set;
sigemptyset(&block_set);
sigaddset(&block_set, SIGINT);
sigprocmask(SIG_BLOCK, &block_set, NULL);
while(1) {
sleep(1);
}
}
Running Example: https://repl.it/repls/RelevantImaginarySearchservice
You can unblock the signal at a later time by calling
sigprocmask(SIG_UNBLOCK, &block_set, NULL);

Why the signal pause will cause the program to sleep forever?

The APUE book says that: If the signal occurs after the test of sig_int_flag but before the call to pause, the process could go to sleep forever.
I don't know why, can somebody tells me?
Thanks a lot.
int sig_int(); /* my signal handling function */
int sig_int_flag; /* set nonzero when signal occurs */
int main() {
signal(SIGINT, sig_int) /* establish handler */
.
.
.
while (sig_int_flag == 0)
pause(); /* go to sleep, waiting for signal */
}
int sig_int() {
signal(SIGINT, sig_int); /* reestablish handler for next time */
sig_int_flag = 1; /* set flag for main loop to examine */
}
If an interrupt signal is issued at the precise time you're describing:
the flag has been checked false: entering loop
signal resets itself, setting the flag to 1, but too late (test has been done)
since loop has already been entered, pause() is called and the program waits
That said, if CTRL+C/SIGINT is triggered another time, you can exit the loop, so it's not that critical, since that signal can be issued manually.
If you want to check that behaviour, I suggest you add a sleep statement:
while (sig_int_flag == 0)
{
printf("Hit CTRL+C in the next 10 seconds to trigger the bug\n");
sleep(10);
pause(); /* go to sleep, waiting for signal */
}
A workaround would be to remove the pause() statement and replace it by a polling loop:
while (sig_int_flag == 0)
{
sleep(1);
}
If a SIGINT occurs anywhere in the loop, including between the while and the sleep, then the worse thing that can happen is that the program waits 1 second before noticing that the flag is set, then it exits the loop, and the other, more plausible case it that the sleep call is interrupted, and the loop is exited immediately, so when the signal is set, there's little visible difference between that and a pause call if we only expect SIGINT.
The question's already answered. However, additional answer can consolidate the idea.
while (sig_int_flag == 0) {
<----- think it signal is caught here before pause btw while and pause()
pause(); /* go to sleep, waiting for signal */
}
Having caught, signal handler runs. After it finishes its task, it returns to a point at which the signal is caught, in main() in this case. So, the point is pause() and pause() is called. It waits again SIGINT to catch. To exemplify it, I add sleep(5) equivalently to catch prior pause().
So, we typically want the second situation. To achieve it always, the aforementioned code block has to be atomic. That's why sigsuspend() is better and should be used.
If you would like to experience the fallible case,
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
volatile sig_atomic_t sig_int_flag = 0; /* set nonzero when signal occurs */
char const * handlerMsg = "in handler\n";
int handlerMsgLen;
void sig_int(int s) {
signal(SIGINT, sig_int); /* reestablish handler for next time */
sig_int_flag = 1; /* set flag for main loop to examine */
write(2, handlerMsg, handlerMsgLen);
}
void mySleep() {
for (int i = 0; i < 5; ++i) {
sleep(1);
fprintf(stderr, "%d ", i + 1);
}
}
int main() {
handlerMsgLen = strlen(handlerMsg);
signal(SIGINT, sig_int); /* establish handler */
while (sig_int_flag == 0) {
mySleep();
pause(); /* go to sleep, waiting for signal */
}
}

Custom SIGINT signal handler - Program still terminates even after signal is caught

I am playing with the signal.h and unistd.h libraries, and I am having some issues. In the code below, when I send the SIGINT signal to my running program by calling CTRL-C, the signal is caught. However, when pressing CTRL-C again, the program terminates. As I understand it, the print statement "Received signal 2" should be printed every time I press CTRL-C.
Is my understanding of this signal incorrect, or is there a bug in my code?
Thanks for your input!
#include "handle_signals.h"
void sig_handler(int signum)
{
printf("\nReceived signal %d\n", signum);
}
int main()
{
signal(SIGINT, sig_handler);
while(1)
{
sleep(1);
}
return 0;
}
Terminal output:
xxx#ubuntu:~/Dropbox/xxx/handle_signals$ ./handle_signals
^C
Received signal 2
^C
xxx#ubuntu:~/Dropbox/xxx/handle_signals$
Edit: Here is the header I've included
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void sig_handler(int signum);
Thanks for your responses. Reading through them now!
Don't use signal, use sigaction:
The behavior of signal() varies across UNIX versions, and has also varied historically across different versions of Linux. Avoid its use: use sigaction(2) instead.
http://man7.org/linux/man-pages/man2/signal.2.html
In the original UNIX systems, when a handler that was established using signal() was invoked by the delivery of a signal, the disposition of the signal would be reset to SIG_DFL, and the system did not block delivery of further instances of the signal.
Linux implements the same semantics: the handler is reset when the signal is delivered.
The behaviour of signal upon receiving the first signal varies on different implementation. Typically, it requires reinstalling the handler after receiving the signal as handler is reset to its default action:
void sig_handler(int signum)
{
signal(SIGINT, sig_handler);
printf("\nReceived signal %d\n", signum);
}
which is one of the reasons you shouldn't use signal anymore and use sigaction. You can see a bare bone example of using sigaction here.

Unix - Control C and Control Z signal pick up issues

I'm experimenting around with the signals offered in Unix. The two I'm focusing on at the moment is Ctrl+C and Ctrl+Z. I want to catch the signal, and display a message to the screen. I got most of it working. Like the message displays when either signal is pressed. However it seems to only work once. I want the message to display each time Ctrl+C or Ctrl+Z are pressed. Like a loop.
#include <stdio.h>
#include <signal.h>
void handler (int signal);
int main ()
{
if (signal(SIGINT, handler) == SIG_ERR)
{
write (2, "Error catching signal C \n",26);
}
if (signal(SIGTSTP, handler) == SIG_ERR)
{
write(2, "Error catching signal Z \n", 26);
}
pause();
}
void handler (int signal)
{
if (signal == SIGINT)
{
write(1, "CONTROLC \n", 11);
}
else if (signal == SIGTSTP)
{
write(1, "CONTROLZ \n", 11);
}
else
{
write(2, "error \n", 8);
}
main();
}
I attempted to use the main function so that it would restart the program again, but I'm assuming its calling main from within a signal so it behaves differently?
Whoa, don't do it that way. :)
What's happening here is that the SIGINT, for example, is masked (blocked) during the execution of the handler. So, re-invoking main from within the handler re-runs main with SIGINT blocked. Thus you see your handler fire only once per signal — it's blocked ever after. (Note that this blocking behavior is not guaranteed by signal, which is one reason you should use sigaction instead.)
The typical signal handler should do as little work as possible, using only async-signal-safe functions, if any. Think of the handler as an interruption to the ordinary flow of your process, a special asynchronous flow which can use its own stack if need be.
If you want the program to behave like a loop, code it like a loop:
static volatile sig_atomic_t flag_int;
static volatile sig_atomic_t flag_tstp;
static void handle_int(int s) { flag_int = 1; } /* register me with sigaction */
static void handle_tstp(int s) { flag_tstp = 1; } /* me, too */
...
while (1) {
pause();
if (flag_int) { printf("CONTROL C\n"); flag_int = 0; }
if (flag_tstp) { printf("CONTROL Z\n"); flag_tstp = 0; }
}
Don't call main() from your signal handler, as your program is now stuck in the signal handler, and it will not call another signal handler for the same signal again while the handler is running.
(That behavior can be changed if you use sigaction() instead of signal() though).
Also see what the pause() call does.
DESCRIPTION
pause() causes the calling process (or thread) to sleep until a signal is delivered that either terminates the process or causes the
invocation of a signal-catching function.
So, your pause(); calls waits until a signal is delivered, and then continues your program.
So, do e.g. this to keep your program running.
for(;;) {
pause();
}
Do not use signal(2), except possibly to set a given signal's disposition to SIG_DFL or SIG_IGN. Its behavior varies among different Unixes.
For portability (among POSIX systems) and better control, you should install user signal handlers via the sigaction(2) syscall. Among other things, that allows you to choose between one-shot and persistent mode when you install the handler.
If you are obligated to use signal(2), then your best bet is for the last thing the handler does to be to reinstall itself as the handler for the given signal (when that's in fact what you want).

C: SIGALRM - alarm to display message every second

So I'm trying to call an alarm to display a message "still working.." every second.
I included signal.h.
Outside of my main I have my function: (I never declare/define s for int s)
void display_message(int s); //Function for alarm set up
void display_message(int s) {
printf("copyit: Still working...\n" );
alarm(1); //for every second
signal(SIGALRM, display_message);
}
Then, in my main
while(1)
{
signal(SIGALRM, display_message);
alarm(1); //Alarm signal every second.
That's in there as soon as the loop begins. But the program never outputs the 'still working...' message. What am I doing incorrectly? Thank you, ver much appreciated.
Signal handlers are not supposed to contain "business logic" or make library calls such as printf. See C11 §7.1.4/4 and its footnote:
Thus, a signal handler cannot, in general, call standard library functions.
All the signal handler should do is set a flag to be acted upon by non-interrupt code, and unblock a waiting system call. This program runs correctly and does not risk crashing, even if some I/O or other functionality were added:
#include <signal.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
volatile sig_atomic_t print_flag = false;
void handle_alarm( int sig ) {
print_flag = true;
}
int main() {
signal( SIGALRM, handle_alarm ); // Install handler first,
alarm( 1 ); // before scheduling it to be called.
for (;;) {
sleep( 5 ); // Pretend to do something. Could also be read() or select().
if ( print_flag ) {
printf( "Hello\n" );
print_flag = false;
alarm( 1 ); // Reschedule.
}
}
}
Move the calls to signal and alarm to just before your loop. Calling alarm over and over at high speed keeps resetting the alarm to be in one second from that point, so you never reach the end of that second!
For example:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void display_message(int s) {
printf("copyit: Still working...\n" );
alarm(1); //for every second
signal(SIGALRM, display_message);
}
int main(void) {
signal(SIGALRM, display_message);
alarm(1);
int n = 0;
while (1) {
++n;
}
return 0;
}
Do not call alarm() twice, just call it once in main() to initiate the callback, then once in display_message().
Try this code on Linux (Debian 7.8) :
#include <stdio.h>
#include <signal.h>
void display_message(int s); //Function for alarm set up
void display_message(int s)
{
printf("copyit: Still working...\n" );
alarm(1); //for every second
signal(SIGALRM, display_message);
}
int main()
{
signal(SIGALRM, display_message);
alarm(1); // Initial timeout setting
while (1)
{
pause();
}
}
The result will be the following one :
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
The alarm() call is for a one off signal.
To repeat an alarm, you have to call alarm() again each time the signal occurs.
Another issue, also, is that you're likely to get EINTR errors. Many system functions get interrupted when you receive a signal. This makes for much more complicated programming since many of the OS functions are affected.
In any event, the correct way to wait for the next SIGALRM is to use the pause() function. Something the others have not mentioned (instead they have tight loops, ugly!)
That being said, what you are trying to do would be much easier with a simple sleep() call as in:
// print a message every second (simplified version)
for(;;)
{
printf("My Message\n");
sleep(1);
}
and such a loop could appear in a separate thread. Then you don't need a Unix signal to implement the feat.
Note: The sleep() function is actually implemented using the same timer as the alarm() and it is clearly mentioned that you should not mix both functions in the same code.
sleep(3) may be implemented using SIGALRM; mixing calls to alarm() and sleep(3) is a bad idea.
(From Linux man alarm)
void alarm_handler(int)
{
alarm(1); // recurring alarm
}
int main(int argc, char *argv[])
{
signal(SIGALRM, alarm_handler);
alarm(1);
for(;;)
{
printf("My Message\n");
// ...do other work here if needed...
pause();
}
// not reached (use Ctrl-C to exit)
return 0;
}
You can create variations. For example, if you want the first message to happen after 1 second instead of immediately, move the pause() before the printf().
The "other work" comment supposes that your other work does not take more than 1 second.
It is possible to get the alarm signal on a specific thread if work is required in parallel, however, this can be complicated if any other timers are required (i.e. you can't easily share the alarm() timer with other functions.)
P.S. as mentioned by others, doing your printf() inside the signal handler is not a good idea at all.
There is another version where the alarm() is reset inside main() and the first message appears after one second and the loop runs for 60 seconds (1 minute):
void alarm_handler(int)
{
}
int main(int argc, char *argv[])
{
signal(SIGALRM, alarm_handler);
for(int seconds(0); seconds < 60; ++seconds)
{
alarm(1);
// ...do other work here if needed...
pause();
printf("My Message\n");
}
// reached after 1 minute
return 0;
}
Note that with this method, the time when the message will be printed is going to be skewed. The time to print your message is added to the clock before you restart the alarm... so it is always going to be a little over 1 second between each call. The other loop is better in that respect but it still is skewed. For a perfect (much better) timer, the poll() function is much better as you can specify when to wake up next. poll() can be used just and only with a timer. My Snap library uses that capability (look for the run() function, near the bottom of the file). In 2019. I moved that one .cpp file to the eventdispatcher library. The run() function is in the communicator.cpp file.
POSIX permits certain of its functions to be called from signal handling context, the async-signal safe functions, search for "async-sgnal safe" here. (These may be understood as "system calls" rather than library calls). Notably, this includes write(2).
So you could do
void
display_message (int s) {
static char const working_message [] = "copyit: Still working...\n";
write (1, working_message, sizeof working_message - sizeof "");
alarm(1); /* for every second */
}
By the way, precise periodic alarms are better implemented using setitimer(2),
since these will not be subject to drift. Retriggering the alarm via software, as done here, will unavoidably accumulate error over time because of the time spent executing the software as well as scheduling latencies.
In POSIX sigaction(2) superceedes signal(2) for good reason:
the original Unix signal handling model was simple. In particular,
a signal handler was reset to its original "deposition" (e.g., terminate
the process) once it was fired. You would have to re-associate
SIGALRM with display_message() by calling signal() just before
calling alarm() in display_message().
An even more important reason for using sigaction(2) is the
SA_RESTART flag. Normally, system calls are interrupted when
a signal handler is invoked. I.e., when then signal handler returns,
the system call returns an error indication (often -1) and errno is
set to EINTR, interrupted system call. (One reason for this
is to be able to use SIGALRM to effect time outs, another is
to have a higher instance, such as a user, to "unblock" the
current process by sending it a signal, e.g.,
SIGINT by pressing control-C at the terminal).
In your case, you want signal handling to be transparent
to the rest of the code, so you would set the SA_RESTART flag
when invoking sigaction(2). This means the kernel should
restart the interrupted system call automatically.
ooga is correct that you keep reloading the alarm so that it will never go off. This works. I just put a sleep in here so you don't keep stepping on yourself in the loop but you might want to substitute something more useful depending on where you are headed with this.
void display_message(int s)
{
printf("copyit: Still working...\n" );
// alarm(1); //for every second
// signal(SIGALRM, display_message);
}
int main(int argc, char *argv[])
{
int ret;
while(1)
{
signal(SIGALRM, display_message);
alarm(1);
if ((ret = sleep(3)) != 0)
{
printf("sleep was interrupted by SIGALRM\n");
}
}
return (0);
}

Resources