Simple Signals - C programming and alarm function - c

#include <stdio.h>
#include <signal.h>
void ALARMhandler(int sig)
{
signal(SIGALRM, SIG_IGN); /* ignore this signal */
printf("Hello");
signal(SIGALRM, ALARMhandler); /* reinstall the handler */
}
int main(int argc, char *argv[])
{
alarm(2); /* set alarm clock */
while (1)
;
printf("All done");
}
I expect the program to print "hello" after 2 seconds, but instead the output is "zsh: alarm ./a.out"
Any idea what is going on?

You're forgetting to set the alarm handler initially. Change the start of main() like:
int main(int argc, char *argv[])
{
signal(SIGALRM, ALARMhandler);
...
Also, the signal handler will probably print nothing. That's because the C library caches output until it sees an end of line. So:
void ALARMhandler(int sig)
{
signal(SIGALRM, SIG_IGN); /* ignore this signal */
printf("Hello\n");
signal(SIGALRM, ALARMhandler); /* reinstall the handler */
}
For a real-world program, printing from a signal handler is not very safe. A signal handler should do as little as it can, preferably only setting a flag here or there. And the flag should be declared volatile.

You're not setting the handler in your main function.
Before you do alarm(2), put the signal(SIGALRM, ALARMhandler); in your main.
It should work then.
Note that your "All Done" will never be printed, because you'll stay in the while(1) loop after the signal processor has run. If you want the loop to be broken, you'll need to have a flag that the signal handler changes.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
/* number of times the handle will run: */
volatile int breakflag = 3;
void handle(int sig) {
printf("Hello\n");
--breakflag;
alarm(1);
}
int main() {
signal(SIGALRM, handle);
alarm(1);
while(breakflag) { sleep(1); }
printf("done\n");
return 0;
}

You are not installing the signal handler first.
You need to tell the system that you want to handle the signal before actually receiving it, so you need to call signal() from main before the signal comes.
int main(int argc, char *argv[])
{
signal(SIGALRM, ALARMhandler); /* install the handler */
alarm(2); /* set alarm clock */
while (1);
}

Andomar is rigth. I test this and,
version 1 prints (every second):
Hi...
Hi...
Hi...
Hi...
BYE
Hi...
...
version 2 prints (every five seconds):
Hi...Hi...Hi...Hi...BYE
Hi...Hi...Hi...Hi...BYE
...
So the code is:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
# define T 5
int flag = T;
void sigalrm_handler(int);
int main(void)
{
signal(SIGALRM, sigalrm_handler);
alarm(1);
while (1);
}
void sigalrm_handler(int sig)
{
if(--flag){
printf("Hi...\n"); /*version 1*/
/*printf("Hi...");*/ /*version 2*/
}else{
printf("BYE\n");
flag=T;
}
alarm(1);
}

Related

C: writing a bash shell, how to mimic bash shell behavior for SIGINT

When receiving a SIGINT signal, the bash shell quits the line the user is currently writing, and prints out a new prompt, but it doens't exit. How can I mimic that behavior? I'm writing my own shell and I want the shell to continue running on SIGINT. I'm not sure how to properly terminate the previous fget from reading from stdin and then print out a new prompt:
my code:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
char *get_args()
{
char *args = calloc(sizeof(char), 1024);
fgets(args, 1023, stdin);
char *pter = strrchr(args, '\n');
if (pter)
*pter = 0;
return args;
}
void sigintHandler(int sig_num)
{
// Reset handler to catch SIGINT next time.
signal(SIGINT, sigintHandler);
printf("Received ctrl c\n");
}
int main(int argc, char *argv[])
{
char host_name[64]; // hostname
gethostname(host_name, 64);
signal(SIGINT, sigintHandler);
while (1)
{
if (isatty(STDIN_FILENO))
{
printf("[%s]$ ", host_name);
char *line = get_args();
printf("\nline: %s\n", line);
}
}
return 0;
};
How can I terminate fgets from running after SIGINT so that the prompt (hostname) can be printed again?
Answer with setlongjmp and sigsetjmp:
After some research, it seemed the easiest way (least lines of code) to cancel an existing fgets, scanf, etc call that's waiting to read from stdin after a SIGINT interrupt is to use a siglongjmp statement.
Using sigsetjmp, you can declare a jump location (in my case it is in main, so that my infinite while loop can print the prompt again. Then, inside the SIGINT handler, you can call siglongjmp.
Relevant code:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
// initialize marker for jump
sigjmp_buf mark;
// handler for SIGINT creates another SIGINT handler
// for the next SIGINT interrupt, and jumps back
// to infinite lopp
void sigintHandler(int sig_num)
{
// Reset handler to catch SIGINT next time.
signal(SIGINT, sigintHandler);
// jump back to main to abort current stdin from fgets
siglongjmp(mark, 1);
}
int main(int argc, char *argv[])
{
// signal handler for SIGINT
signal(SIGINT, sigintHandler);
// set the marker to this point in main
sigsetjmp(mark, 1);
while (1)
{
if (isatty(STDIN_FILENO))
{
// some code that prints the prompt in the form
// of username#hostname:cwd$
}
}
return 0;
};

signal handler in child thread

I tried to install SIGINT handler for the child thread in the code below. I expect the child thread to print hello when it receives SIGINT from the parent process. However, nothing comes out and the program exits immediately.
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
typedef struct proxy_node_t{
pthread_t sub_thread;
pthread_t p_self;
}proxy_node;
proxy_node* proxy;
static void proxy_singnal_handler(){
printf("Hello\n");
return;
}
static void* t_consensus(void *arg){
signal(SIGINT,proxy_singnal_handler);
sleep(1);
return NULL;
}
int main(int argc, char **argv)
{
proxy = (proxy_node*)malloc(sizeof(proxy_node));
proxy->p_self = pthread_self();
pthread_create(&proxy->sub_thread,NULL,t_consensus,NULL);
pthread_kill(proxy->sub_thread,SIGINT);
sleep(1);
return 0;
}
There are several problems.
1) The signal handler signature is not correct. It should take an int whereas you define it with no parameter.
i.e.
static void proxy_singnal_handler(){
should be
static void proxy_singnal_handler(int sig){
2) You can't call functions that are not async-signal-safe from a signal handler (printf() in your case). See signal(7) for details. You can instead use write(2) to print that message:
printf("Hello\n");
can be:
write(1, "Hello\n", 6);
3) When main thread sends SIGINT, the t_consensus thread might not have even started. So, signal() may not have been installed yet. So, you need to make sure signal() is installed before pthread_kill() could send SIGINT.
Just to demonstrate it, I have added some sleep calls (see comments in the code). But please note that sleep() is not a good way to synchronization and if you intend to adapt this example then you should use a conditional variable instead.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
typedef struct proxy_node_t{
pthread_t sub_thread;
pthread_t p_self;
}proxy_node;
proxy_node* proxy;
static void proxy_singnal_handler(int sig){
write(1, "Hello\n", 6);
return;
}
static void* t_consensus(void *arg){
signal(SIGINT,proxy_singnal_handler);
while(1); /* infinite loop */
return NULL;
}
int main(int argc, char **argv)
{
proxy = (proxy_node*)malloc(sizeof(proxy_node));
proxy->p_self = pthread_self();
pthread_create(&proxy->sub_thread,NULL,t_consensus,NULL);
sleep(2); /* delay to ensure signal handler is installed */
pthread_kill(proxy->sub_thread,SIGINT);
sleep(2); /* delay to ensure signal gets executed before the process exits */
return 0;
}
Since #Maxim Egorushkin wanted to see a solution that exits gracefully and uses semaphores:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <semaphore.h>
typedef struct proxy_node_t{
pthread_t sub_thread;
pthread_t p_self;
}proxy_node;
proxy_node* proxy;
static void proxy_singnal_handler(int sig)
{
write(1, "Hello\n", 6);
return;
}
sem_t sema1;
sem_t sema2;
static void* t_consensus(void *arg)
{
signal(SIGINT,proxy_singnal_handler);
sem_post(&sema1); /*notify main thread that signal-handler is installed*/
sem_wait(&sema2); /*ensure thread exists to be pthread_kill'ed, could use sigsuspend instead*/
return NULL;
}
int main(int argc, char **argv)
{
sem_init(&sema1, 0, 0);
sem_init(&sema2, 0, 0);
proxy = (proxy_node*)malloc(sizeof(proxy_node));
proxy->p_self = pthread_self();
pthread_create(&proxy->sub_thread,NULL,t_consensus,NULL);
sem_wait(&sema1); /*wait until the thread has installed the signal handler*/
pthread_kill(proxy->sub_thread,SIGINT);
sem_post(&sema2); /*not strictly necessary if the thread uses sigsuspend*/
pthread_join(proxy->sub_thread, NULL);
free(proxy); /*not strictly necessary before exiting*/
sem_destroy(&sema1);
sem_destroy(&sema2);
return 0;
}

Counter in C Programming

I am trying to set up a counter for my programme to count how many times a signal was sent. I am trying to achieve the program to exit after ctrl +c was pressed twice. I have most of the code but just don't know how to link the counter to the if section. Here is my code.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
// user-defined signal handler for alarm.
int cnt=0;
void my_handler(int signo)
{
while ( cnt < 2){
if (signo == SIGINT)
{
printf("Press ctrl c to stop\n");
exit(0);
}
}
}
int main(void)
{
signal(SIGINT,my_handler);
while(1){
printf(" I am running into infinite loop.., stop me if you dear..\n");
sleep(1); /* wait until alarm goes off */
}
} /* main */
I tried out the above code and it seems that the counter will stay at 0 forever and the programme exit immediately as soon as ctrl+c was pressed.
You can't do much safely in a signal handler, and definitely no I/O. For maximum portability, there are really only a handful of things a signal handler can do to affect global state:
Assign to a volatile sig_atomic_t variable
Make calls to signal
abort, exit, etc. on error
You can't do I/O safely. The safe thing to do is set a flag that the main thread can check and do your printing for you. If printing isn't necessary, the first call to your handler could just unregister itself, restoring the default behavior with SIG_DFL (or registering a new "second Ctrl-C" handler if you need to do something special) so the second Ctrl-C kills as normal.
Replace the while statement with an if one. If cnt is lower than 2, then print your message and count by using cnt++; else do something else
Signals are a little more involved to get right.
You should either use sigaction or a custom sigaction wrapper as signal doesn't have clearly defined semantics. Registering the handler may fail.
If you want to set a flag, it should be volatile sigatomic_t, you shouldn't do buffered IO in the handler.
With the wrapper and flag approach, you could do something like:
typedef void (Sigfunc)(int);
Sigfunc* reliableSignal(int signo, Sigfunc *func);
// user-defined signal handler for alarm.
volatile sig_atomic_t cnt=0;
void my_handler(int signo){
if(cnt++ == 1)
exit(0);
}
int main(void) {
if(reliableSignal(SIGINT,my_handler)<0){ perror("Signal"); exit(1); }
while(1){
printf(" I am running into infinite loop.., stop me if you dear..\n");
sleep(1); /* wait until alarm goes off */
}
} /* main */
Sigfunc* reliableSignal(int signo, Sigfunc *func)
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (signo == SIGALRM) {
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
} else {
act.sa_flags |= SA_RESTART;
}
if (sigaction(signo, &act, &oact) < 0)
return(SIG_ERR);
return(oact.sa_handler);
}
In this example you must press twice Ctrl-C within 300ms.
So if you keep Ctrl-C pressed the program will stop otherwise not.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
int ctrlcs=0;
void cchandler(int signum){
printf("Press again to quit.\n");
ctrlcs+=1;
if (ctrlcs==2) {
signal(SIGINT, SIG_DFL);
}
usleep(300000); // delay for the second Ctrl-C
}
int main(){
signal(SIGINT, cchandler);
while(1) {
printf(" I am running into infinite loop.., stop me if you dare..\n");
sleep (5);
ctrlcs=0;
}
}

How to avoid scanf after my signal handler function in C?

I have this code:
#include <stdio.h>
#include <signal.h>
void signal_handler(int signal) {
printf("Caught signal in CHILD.\n");
}
int main(void) {
int s;
signal(SIGTSTP, signal_handler);
while(1){
printf("%s#%s/# ",getlogin(),get_current_dir_name());
scanf("%d",&s);
}
return 0;
}
when i run the code it prints:
something: ^ZCaught signal in CHILD.
As far i understand that the scanf doesn't execute when i press the ctr-z. Although after the printf inside my function it goes straight to the scanf, waits for input and then starts the loop again.Is there any way to avoid scanf when i press ctr-z and start the while loop again? I tried something like that
void signal_handler(int signal) {
printf("Caught signal in CHILD.\n");
printf("%s#%s/# ",getlogin(),get_current_dir_name());
}
but it didn't work. After the second printf goes straight to the scanf, waits for input and then starts the loop again. Can i, somehow, start the loop again?
The signal handler is interrupting scanf during its read of STDIN. However, because of the way you set signal disposition, the read system call restarts immediately upon return of the signal handler. That's why you are "stuck" in the scanf rather than back at the top of your loop.
One important thing you can do is to use sigaction rather than signal. This will force you to specify the behavior of interrupted calls: restart them or not?
The next thing to do is to limit your signal handlers to functions that are async-signal-safe, lest you risk misery.
As an aside, another change to make is to give us all the required includes (<unistd.h>?) and defines (_GNU_SOURCE ?) to make your program work.
As commented the worst solution should be:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
void signal_handler(int signal) {
printf("Caught signal in CHILD.\n");
exit(1);
}
int main(void) {
int s;
signal(SIGTSTP, signal_handler);
while(1){
printf("test\n");
scanf("%d",&s);
}
return 0;
}
Better solution
#include <stdio.h>
#include <signal.h>
static volatile int keepRunning = 1;
void signal_handler(int signal) {
printf("Caught signal in CHILD.\n");
keepRunning = 0;
}
int main(void) {
int s;
signal(SIGTSTP, signal_handler);
while(keepRunning){
printf("test\n");
scanf("%d",&s);
}
return 0;
}
EDIT after comments
#include <stdio.h>
#include <signal.h>
static volatile int skipPrintf= 1;
void signal_handler(int signal) {
printf("Caught signal in CHILD.\n");
skipPrintf= 1;
}
int main(void) {
int s;
signal(SIGTSTP, signal_handler);
while(1){
if (skipPrintf == 0)
{
printf("test\n");
}
else
{
skipPrintf = 0;
}
scanf("%d",&s);
}
return 0;
}

how to intercept linux signals ? (in C)

I need to intercept and trace signals from any binaries, like strace does it under linux.
I don't need a so verbose output like the real one strace.
I just want to know how it works, how can I intercept signal and how can I trace them.
Thanks in advance :)
strace uses the ptrace() system call for tracing, which also allows you to intercept (and possibly manipulate) signals sent to the process.
Here's a tiny example:
#include <sys/ptrace.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
/* simple example, child is traced, uses alarm which causes a signal to be
* set up */
pid_t child;
child = fork();
if (child == 0)
{
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
alarm(3);
while(1)
{
}
exit(0);
}
/* parent */
while(1)
{
int wstatus;
int signum;
wait(&wstatus);
if (WIFEXITED(wstatus) || WIFSIGNALED(wstatus))
break;
signum = WSTOPSIG(wstatus);
printf("child stopped with signal %d\n", signum);
/* resume execution */
ptrace(PTRACE_CONT, child, NULL, signum);
}
return 0;
}
This is a simple implementation:
Put somewhere in your int main() several calls to signal(), one for each signal you want to catch. The first argument is the signal name; the second is the signal handler function (more on that below):
signal(SIGFPE, SignalHandler);
signal(SIGILL, SignalHandler);
signal(SIGINT, SignalHandler);
signal(SIGSEGV, SignalHandler);
signal(SIGTERM, SignalHandler);
#ifndef WIN32
signal(SIGHUP, SignalHandler);
signal(SIGQUIT, SignalHandler);
signal(SIGKILL, SignalHandler);
signal(SIGPIPE, SignalHandler);
signal(SIGCHLD, SignalHandler);
#endif
Now, write a signal function. It must return void and accept an int: void SignalHandler(int signal_number):
void SignalHandler(int signal_number)
{
printf("Received signal: %s\n", strsignal(signal_number);
// Do something
}
That's it! You can also test it by sending a signal to yourself with the function raise(SIGNAL_NAME); for example, try raise(SIGTERM);!
Intercepting signals to other processes is something you should not do for any reason other than debugging them. This is what strace is intended for. Processes should be capable of handling their own signals.
Needless to say, if you are writing a debugger, understand ptrace().

Resources