Why the printf is never executing after an alarm? - c

I'm trying to do something simple with alarms, however the printf is never executing after I do the alarm, why's that?
#include <stdio.h>
#include <signal.h>
int main() {
alarm(3);
printf("Hello...\n");
alarm(6);
while(1);
printf("Hello2\n");
}
I want hello and hello2 to be printed, only hello is being printed for now

You didn't specify a handler for SIGALRM, and its default behavior (per man 7 signal) is to terminate the program. Even if you did specify a handler, after it ran, you'd still be in the while(1) loop.
Here's how you'd modify your program to fix both of those problems:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
volatile sig_atomic_t got_sigalrm = 0;
void handle_sigalrm(int signum) {
got_sigalrm = 1;
}
int main() {
struct sigaction act = { .sa_handler = handle_sigalrm };
sigaction(SIGALRM, &act, NULL);
alarm(3);
printf("Hello...\n");
alarm(6);
while(!got_sigalrm);
printf("Hello2\n");
}

Related

Unable to reassign signal handler second time

I have a simple code which uses two signal handlers for "Segmentation fault" signal. First one works when signal happens and after longjmp, I do reassigning of handler with second one for that signal. Unfortunately, the flow of code doesn't reach necessary handler and I still get "Segmentation fault".
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
int i;
int ci;
jmp_buf m_env_buffer;
jmp_buf max_env_buffer;
void handler(int signum){
printf("sigsegv on i:[%d]", i);
ci = (++i);
longjmp(m_env_buffer,1);
}
void top_handler(int signum){
printf("sigsegv on max i:[%d]", i);
longjmp(max_env_buffer,10);
}
int main(void) {
signal(SIGSEGV, handler);
char * pstart = "loremipsum";
int m_cell = 0;
char m_cell_v;
int point;
point = setjmp(m_env_buffer);
if(point == 0){
for(i=0; ;i--){
m_cell_v = pstart[i];
}
}
//this wasn't invoked
signal(SIGSEGV, top_handler);
point = setjmp(max_env_buffer);
if(point == 0){
for(i=ci; ;i++){
char cur = pstart[i];
if(cur==10)
printf("\n");
printf("%c",cur);
}
}
puts("finish");
return 0;
}
signal() should not be used. It has unreliable semantics. On your system the default action (termination) is performed when the second SIGSEGV is received. The second call to signal() has effectively no effect.
You should use sigaction() instead. In your case you can use the following function instead of signal():
void set_signal (int signum, void (*handler)(int))
{
struct sigaction act;
act.sa_handler = handler;
sigemptyset (&act.sa_mask);
act.sa_flags = SA_NODEFER;
act.sa_restorer = NULL;
sigaction (signum, &act, NULL);
}
In the future, read the documentation at your disposal. A good ressource is the glibc manual. It has a good chapter on signal handling.

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;
}

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;
}

Infinite loop - Waiting for the SIGRTMIN

I'm trying to use the signal SIGRTMIN, in order to do_stuff when it gives me permission. It's my first time working with signals. The problem is that I'm stuck in
while (go == 0){printf("Waiting\n");}
This is my code:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
volatile sig_atomic_t go = 0;
void handler (int sig)
{
go = 1;
signal (sig, handler);
}
void do_stuff (void)
{
puts ("Doing stuff while waiting for alarm....");
}
int main (void)
{
int i=0;
signal (SIGRTMIN, handler);
while(i<5){
while (go == 0){printf("Waiting\n");}
do_stuff();
i++;
}
return EXIT_SUCCESS;
}
Can you help? Thanks in advance!
You need to get the SIGRTMIN signals sent from somewhere; it won't respond to the signal until it is sent. The simplest thing is to have it send itself signals, so here's a mildly revised version of your code.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#ifndef SIGRTMIN
#define SIGRTMIN SIGUSR1
#endif
volatile sig_atomic_t go = 0;
static
void handler(int sig)
{
go = 1;
signal(sig, handler);
}
static
void do_stuff(void)
{
puts("Doing stuff while waiting for alarm....");
go = 0;
}
int main(void)
{
signal(SIGRTMIN, handler);
for (int i = 0; i < 5; i++)
{
while (go == 0)
{
puts("Waiting...");
struct timespec t = { .tv_sec = 0, .tv_nsec = 300000000 };
nanosleep(&t, 0);
kill(getpid(), SIGRTMIN);
}
do_stuff();
}
return EXIT_SUCCESS;
}
Example run:
Waiting...
Doing stuff while waiting for alarm....
Waiting...
Doing stuff while waiting for alarm....
Waiting...
Doing stuff while waiting for alarm....
Waiting...
Doing stuff while waiting for alarm....
Waiting...
Doing stuff while waiting for alarm....
Not very exciting output, but it is at least working. The nanosleep() sleeps for 0.3 seconds.

Signal handler is not getting called in main function

I am trying to study how signal handlers work. I have written code where i cause an alarm signal to raise once in every 100us. But, the signal is not raised. Here is the code :
#include <signal.h>
#include <ucontext.h>
#include <sys/time.h>
#include<unistd.h>
#include<setjmp.h>
#include<stdio.h>
void handler(int signum, siginfo_t *ptr, ucontext_t *old_context)
{
printf("inside handler");
}
int main()
{
struct itimerval itv;
struct sigaction act;
act.sa_handler = handler;
act.sa_flags=SA_RESTART|SA_SIGINFO;
sigaction(SIGVTALRM, &act, 0);
itv.it_interval.tv_sec=0;
itv.it_interval.tv_usec=100;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 100;
setitimer(ITIMER_VIRTUAL, &itv, NULL); //engage timer
int i=0;
while(i<=100)
{
printf("main\n");
i++;
}
}
can some one explain what i am doing wrong?
Thanks
Your loop is probably taking less than 100us to run, try this:
volatile int i=0;
while(i<=100000000)
{
//printf("main\n");
i++;
}
I removed the printf so the output is not flooded, and made i volatile so the compiler won't optimize the loop.

Resources