I was trying this program from Advance Programming in Unix Environment.
#include<stdio.h>
#include<signal.h>
static void handler(int sig){
if(sig == SIGUSR1)
printf("handled user1 signal");
else if(sig == SIGUSR2)
printf("handles user2 signal");
else
printf("unkown signal");
}
int main(){
if(signal(SIGUSR1, handler) == SIG_ERR)
printf("can't handle signal SIGUSR1");
if(signal(SIGUSR2, handler) == SIG_ERR)
printf("can't handle signal SIGUSR2");
for(;;)
pause();
return 0;
}
I am using Ubuntu 11.10. I compile the program with gcc and then run a.out as indicated in the book.
$./a.out&
[1]+ 1345
$ kill -USR1 1345
But there is no output printed. The program keeps running in backgound and I have to kill it.
Other things I have tried:
Tried handling SIGINT to see if running program in background is causing problems. Still no output.
Downloaded latest release of FreeBSD and tried the same program on it, but with same problem.
I put a printf statement before setting signal handler:
int main(){
printf("printf is working...");
//exit(0);
if(signal(SIGUSR1, handler) == SIG_ERR)
...
when exit() is commented, there is no output. When I uncomment it, the output is printed.
Please tell me what am I doing wrong in this?
PS: Don't suggest using sigaction(). I am learning Unix Programming, not building any practical application.
The output from printf is buffered. That means it's stored in memory until flushed to the output. The best way to flush text in printf is to end the text with a newline. You can also flush manually with the fflush function.
However, you should be cautioned that using output functions like printf and fflush is not considered safe in signal handlers.
Related
Suppose we have application on Linux, pure C. Application consists of several functions - f1, f2 and f3, which receive a structure. One element of the structure is debug_mode, with values ON or OFF.
How can I switch debug mode in f1, f2 and f3 (for example, some printfs) when the structure has debug_mode == ON?
Should I always use if statements to check debug_mode for every incoming structure or there is some another best practise to not use always if statements?
For example, these could be traces in telecom products, where we could collect some trace data for a specified subscriber.
You can change it during runtime like this :
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#define FALSE 0
#define TRUE 1
volatile sig_atomic_t GLOBAL_DEBUG = FALSE;
void sig_handler(int signo)
{
if (signo == SIGUSR1) {
// printf("received SIGUSR1\n");
GLOBAL_DEBUG = TRUE;
} else if (signo == SIGUSR2) {
GLOBAL_DEBUG = FALSE;
// printf("received SIGUSR2\n");
}
}
int main (int argc, char **argv) {
if (signal(SIGUSR1, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGUSR1\n");
if (signal(SIGUSR2, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGUSR2\n");
while (TRUE) {
if (GLOBAL_DEBUG) printf ("DEBUG == TRUE\n");
printf ("Hello world\n");
sleep(1);
}
}
And the switch GLOBAL_DEBUG during runtime like this :
user#host:~ $ kill -SIGUSR2 <pid of program>
user#host:~ $ kill -SIGUSR1 <pid of program>
BTW, read signal-safety(7) (explaining why printf should be avoided inside signal handlers) and signal(7). sig_atomic_t is specified in the C11 standard (see n1570).
You could use signals (see signal(7) & signal-safety(7)), as explained in mbieren's answer. Of course you cannot call printf (or any non async-signal-safe function) from a signal handler, and the flag should be declared as volatile sig_atomic_t GLOBAL_DEBUG;
You could design your program otherwise. Perhaps your program has already some event loop (e.g. because it is a GUI application). Then you could add some RPCJSON service (or some HTTP one, or your own socket(7) or unix(7) based protocol, probably some text-based one) to your program. You'll find many libraries to help you (for example, libonion enables you to add some HTTP service to your program; so you might change the debug flag via your web server!).
You don't tell enough about your program to get more precise help.
I want to make my program sleep upto 10 seconds even the signal is occured. So, I tried the following program.
Program:
#include<stdio.h>
#include<signal.h>
#include<errno.h>
int main()
{
printf("PID: %d\n",getpid());
int unslept=10;
while(unslept>0){
unslept=sleep(unslept);
if(errno==EINTR)
continue;
}
return 0;
}
Output:
$ ./a.out
PID: 18935
User defined signal 1
$
I expect the above program will execute 10 seconds even the signal is interrupted. I exeperiment it like, in one terminal I
executed this program. And using another terminal using kill command I sent the SIGUSR1 signal to this process. But, the same problem
occurs. Once the signal is passed, the program terminates. So, is there any way to execute my program upto 10 seconds without affecting
any signal.
You can ignore the signal. See the below example, in that example, if the SIGUSR1 signal is interrupted, it just ignore the signal using the SIG_IGN.
#include<stdio.h>
#include<signal.h>
int main(void)
{
if (signal(SIGUSR1, SIG_IGN) == SIG_ERR)
perror("SIGUSR1");
sleep(30);
}
You can use signal handling mechanism. Register your method that will handle interrupt signals and just ignore it that in your function.
// signal handler
void my_function(int sig){
//do nothing
}
// register signal
signal(SIGNAL_ID, my_function);
While going through signals, I found that statement inside the handler was not printed. Here is the code I used:
#include"stdio.h"
#include"signal.h"
#include"unistd.h"
void handlerSIGINT(int sig)
{
if(sig == SIGINT)
printf("\nFinally caught SIGINT...");
}
int main()
{
printf("Hello ... soon u'll receive a signal");
if(signal(SIGINT, handlerSIGINT) == SIG_ERR)
{
printf("error in SIGINT handling");
}
while(1)
sleep(1);
/*now press control + C to see the effect */
return 0;
}
I got the following output when I run the program :
[root#node1 mytest]# ./a.out
^CHello ... soon u'll receive a signal
^CFinally caught SIGINT...
^CFinally caught SIGINT...
^CFinally caught SIGINT...
^Z
[1]+ Stopped ./a.out
My confusion is : When I first pressed "Ctrl+C" it didn't print the message in the handler i.e. "Finally caught SIGINT..." .But from the second time it started printing the message. Can anyone explain why is this happening...
void handlerSIGINT(int sig)
{
if (sig == SIGINT)
printf("\nFinally caught SIGINT...");
}
Here in the signal handler, the output is not terminated by a new line, and by default, the standard output is line buffered, so it's only shown when the next time it sees the \n in the beginning. Change it to:
printf("Finally caught SIGINT...\n");
you would probably see the result as expected. Note, however, you should avoid using printf in a signal handler.
I have write a program by C and run it in Ubuntu,the main code is follow:
int main(){
pid_t pid=fork();
if(pid==0){
printf("d");
exit(0);
}
else{
printf("a");
sleep(4);
}
}
The question is: why the code sleep(4); run before printf("a");
hope someone can give me a answer,thanks!
It is not. Most probably, printf() buffered its output until a chance to output the buffer (in your case, when the process terminated).
Q: why the code sleep(4) run before printf("a")?
A: printf("a") actually runs BEFORE "sleep(4)", just like you see in the code.
However, it doesn't DISPLAY immediately.
The issue is "buffering".
Look here for more details:
buffering behaviour of stdout in c
http://www.pixelbeat.org/programming/stdio_buffering/
SUGGESTED ALTERNATIVE:
pid_t pid=fork();
if(pid==0){
fprintf(stderr, "d");
exit(0);
}
else{
fprintf(stderr, "a");
sleep(4);
}
The reason is that "stderr" is unbuffered: you'll see the output immediately.
Alternatives to using stderr include calling fflush(stdout) or modifying the stream.
It's not, but it may appear that way. printf puts its output into a buffer that probably only gets flushed after the sleep runs. Try putting a call to fflush(stdout) after the printf, but before the call to sleep.
I wrote console program that detects SIGINT, so when user press Ctrl+C program performs some actions and terminates.
But when I redirect this program with pipe to any other, for example:
./my_program | tee xxx
SIGINT never comes to my handler. Despite this program terminates.
Handing SIGTERM gives no effects. SIGTERM does not come after Ctrl+C too.
How can I detect that program is aborted by Ctrl+c in all situations?
My test case with SIGINT and SIGPIPE:
#include <csignal>
#include <cstdio>
bool break_request=false;
bool term_request=false;
extern "C" void break_handler(int)
{
break_request=true;
printf("Ctrl+C detected\n");
}
extern "C" void term_handler(int)
{
term_request=true;
printf("pipe detected\n");
}
int main()
{
signal(SIGINT,break_handler);
signal(SIGPIPE,term_handler);
while(true)
{
if(break_request)
{
printf("break request handled\n");
break;
}
if(term_request)
{
printf("pipe request handled\n");
break;
}
}
printf("terminating\n");
}
Your printf output is going down the pipe. Use fprintf(stderr, "...") instead.
If your program is used in a pipe, it will get SIGPIPE if it writes when there's no reader on the other side.
Just install a SIGPIPE handler.