handle SIGINT with scanf in loop - c

I have to take input from user in a while loop and then take some action. And I also want to exit my code on ctrl+c input.
void my_signal_handler(int sig)
{
running = false;
signal(sig, SIG_IGN);
}
int main(void)
{
struct sigaction sa = {{0}};
sa.sa_handler = &my_signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGINT, &sa, NULL) != 0)
{
fprintf(stderr, "sigaction error\n");
return -1;
}
while(running)
{
printf("enter number: ");
scanf("%d", &num);
// take action based on number
}
}
Problem with this code is after pressing ctrl+c, it doesn't exit but it waits for input for scanf. So once I press an extra key, the program exits (signal handler gets called).
How can I remove this extra step of giving input to scanf after pressing ctrl+c ?

You should install the signal handler. At the very least, add
signal(SIGINT, my_signal_handler);
inside your main before the while(running), but better use sigaction(2).
You should also know that stdio is buffering; usually stdout is line-buffered when it is a terminal (but see setvbuf(3) and friends). So you should either call fflush(3) (probably as fflush(NULL);) before the scanf inside the loop, or terminate every printf format control string with an explicit \n.
At last, scanf(3) can fail and is returning the count of scanned items, which you should test.
BTW, your  main is wrong, should be defined as int main(void) or preferably int main(int argc, char**argv).
However (assuming you are on Linux), read very carefully signal(7) (notice what is said about signal handlers and async-signal safe functions) and POSIX signal.h documentation and declare your running flag as
volatile sigatomic_t running;
(or perhaps, in C11, as volatile _Atomic bool running;)
The volatile qualifier is very important. Otherwise, the compiler is allowed to optimize (and e.g. pretend that running is always true).
Notice that using signal(2) is often a bad idea. First, if you really need signal handling, you'll better use sigaction(2). Then your call to signal(sig, SIG_IGN); is, in your case, useless (since the running volatile flag would have been changed in the signal handler). At last, for multiplexing input (& output), you could use poll(2) which can be used to wait and test if there is some available input on stdin (actually STDIN_FILENO which is 0), and more generally to implement event loops. You could use (instead of poll which I strongly recommend) the old and nearly obsolete select(2), but you'll rather use poll(2). See also epoll(7) & inotify(7) but you probably don't need them.
Be aware that in terminals, stdin is often a tty (check that with isatty(3)) following the line discipline (so some of the line buffering happens inside the kernel). Read the tty demystified page. Consider using the GNU readline library and function (or perhaps ncurses), which might be what you really need.
Read also Advanced Linux Programming and take the habit of reading the documentation of every function that you are using.

Related

printf function on multi thread program

I'm writing a simple program in c, the program has two threads and two global's var, but the printf function not working, I know that printf is not thread safe and also if I will add \n in the print it will work, but I want to understand why it's not working without that?
I'm adding the code,
#include <pthread.h>
#include <stdio.h>
int i;
int j;
void* runi(void* _temp)
{
while(1)
{
i++;
if(i==1000)
{
printf("i: %d",i);
}
}
return NULL;
}
void* runj(void* _temp)
{
while(1)
{
j++;
if(j==1000)
{
printf("j: %d",j);
}
}
return NULL;
}
main ()
{
pthread_t threadI,threadJ;
pthread_create(&threadI,NULL,runi,NULL);
pthread_create(&threadJ,NULL,runj,NULL);
pthread_join(threadI,NULL);
pthread_join(threadJ,NULL);
return 0;
}
printf is somehow thread safe* (see discussion in unlocked_stdio(3)..., and consider flockfile(3)) but stdio is buffered, and you should call fflush(3) in your routines.
(printf is perhaps thread safe because two concurrent printf might not intermix their output, but nothing is told about flushing buffers)
So code instead
if(i==1000) {
printf("i: %d",i);
fflush(stdout);
}
(then you'll see some output)
BTW, I recommend ending most of your printf format control strings with a newline \n.... You could also add some delay by doing some nanosleep(2) or usleep(3) in your runi & runj routines.
It is the buffering which explains that you are disappointed. And stdout should be buffered for efficiency reasons (see setvbuf(3)...). Be aware that system calls (listed in syscalls(2) for Linux) such as write(2) are quite expensive operations. On Linux use strace(1) to understand what system calls are done.
If you want to understand the implementation of printf on Linux, study the source code of your C standard library - which is free software. It probably is GNU glibc, but could be something else like musl-libc, etc.
BTW, your threads are never ending (since runi and runj never return), and you pthread_join them. That call is blocking indefinitely. Use ltrace(1) to observe that.
You could also consider adding some sleep(2); fflush(stdout); in your main before the first pthread_join; you'll then observe some output.
At last, for such experiments, I recommend some periodic printing. Replace the i==1000 condition by i%10000 == 0 ....
You never explicitly flush your stdout so its gets flushed when its buffer (perhaps 8Kbytes) is full, or at end of your main (which is not reached in your case). Jonathan Leffler cleverly commented that you might need to wait an hour for that (buffer full condition) to happen.
Beware of race conditions and of undefined behavior.

Why does alarm() cause fgets() to stop waiting?

I am playing around with signals in C. My main function basically asks for some input using fgets(name, 30, stdin), and then sits there and waits. I set an alarm with alarm(3), and I reassigned SIGALRM to call a function myalarm that simply calls system("say PAY ATTENTION"). But after the alarm goes off, fgets() stops waiting for input and my main fn continues on. This happens even if I change myalarm to just set some variable and do nothing with it.
void myalarm(int sig) {
//system("say PAY ATTENTION");
int x = 0;
}
int catch_signal(int sig, void (*handler)(int)) { // when a signal comes in, "catch" it and "handle it" in the way you want
struct sigaction action; // create a new sigaction
action.sa_handler = handler; // set it's sa_handler attribute to the function specified in the header
sigemptyset(&action.sa_mask); // "turn all the signals in the sa_mask off?" "set the sa_mask to contian no signals, i.e. nothing is masked?"
action.sa_flags = 0; // not sure, looks like we aren't using any of the available flags, whatever they may be
return sigaction(sig, &action, NULL); // here is where you actually reassign- now when sig is received, it'll do what action tells it
}
int main() {
if(catch_signal(SIGINT, diediedie)== -1) {
fprintf(stderr, "Can't map the SIGINT handler");
exit(2);
}
if(catch_signal(SIGALRM, myalarm) == -1) {
fprintf(stderr, "Can't map the SIGALAM handler\n");
exit(2);
}
alarm(3);
char name[30];
printf("Enter your name: ");
fgets(name, 30, stdin);
printf("Hello, %s\n", name);
return 0;
}
Why does alarm() make fgets() stop waiting for input?
Edit: Added code for my catch_signal function, and, as per one of the comments, used sigaction instead of signal, but the issue persisted.
The answer is most likely going to be OS/system specific.
(As stated by Retr0spectrum) The fgets() function often makes system calls, such as read(). System calls can terminate if a signal is detected. In the case of this question, the fgets() function has made a system call (likely the read() system call) to read a character from stdin. The SIGALRM causes the system call to terminate, and set errno to EINTR. This also causes the fgets() function to terminate, without reading any characters.
This is not unusual. It's just how the OS implements signals.
To avoid this problem, I will often wrap fgets() function in a loop like this:
do {
errno=0;
fgets(name, 30, stdin);
} while(EINTR == errno);
It will require that you: #include <stdio.h>
(As suggested by TonyB).
As to the question of why the alarm signal interrupts the read, there are two reasons:
It's the way Unix used to do it, and it was because it was much easier to implement in the OS. (On the one hand this sounds kind of lame, but the "don't sweat the hard stuff" attitude was responsible in part for the success of Unix in the first place. This is the topic of Richard P. Gabriel's epic Worse Is Better essay.)
It makes it easy to implement a read that times out and gives up, if that's what you want. (See my answer to this other question.)
But, as other comments and answers discuss, the interrupting behavior is somewhat obsolete; most modern systems (Unix and Linux, at least) now automatically restart an interrupted system call such as read, more or less as you were wishing. (Also as pointed out elsewhere, if you know what you're doing you may be able to select between the two behaviors.)
In the end, though, it's a grey area; I'm pretty sure the C standard leaves it unspecified or implementation-defined or undefined what happens if you interrupt a system call with an alarm or other signal.

Signal issue when enter Ctrl+C

I am a newbie in Linux programming.I copied the code below from a book:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void ouch (int sig)
{
printf("OUCH! - I got signal %d\n", sig);
(void) signal(SIGINT, SIG_DFL);
}
int main ()
{
(void) signal(SIGINT, ouch);
while(1)
{
printf("Hello World!\n");
sleep(1);
}
}
It was expected to print something when Ctrl+C was entered.But it do nothing but print Hello World!.
EDIT:
I am so sorry that I have binded the Ctrl+C as a short-cut key for copy.
Sorry for trouble caused.
My Suggestion is don't use printf in siginal handler (ouch), it may be undefined behavior. Async-signal-safe functions: The list of safe functions that can be call in signal handler man page.
It is not safe to call all functions, such as printf, from within a signal handler.
A useful technique is to use a signal handler to set a flag and then check that flag
from the main program and print a message if required.
Reference: Beginning Linux Programming, 4th Edition,In this book exactly your code is explained, Chapter 11: Processes and Signals, page 484
An additional helpful link:
Explanation: Use reentrant functions for safer signal handling
Sorry, I can't see a question here... but I can guess what you are interested in.
printf() is a stateful function, thus not reentrant. It uses a FILE structure (variable name is 'stdin') to keep it's state. (It is like calling fprintf(stdin,format,...)).
That means, dependant on implementation and 'luck', calling printf() from a signal handler may print what you expect, but also may print nothing or may even crash or worse, smash your memory! Anything could happen.
So, just don't call functions from within a signal handler that are not explicitely marked 'signal-safe'. You will avoid lot's of headaches in the long term.
Put an fflush(stdout) in your signal handler. It was just buffered, then the second SIGINT exited the program before the buffer could be flushed.

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.

snprintf in signal handler creates segmentation fault if started with valgrind

This very simple C program gives me a segmentation fault when running it with valgrind.
Its runs fine when started normal.
It crashes when you send the USR1 signal to the process.
The problem seems to be the way snprintf handles the formatting of the float value, because it works fine if you use a string (%s) or int (%d) format parameter.
P.S. I know you you shouldn't call any printf family function inside a signal handler, but still why does it only crash with valgrind.
#include <stdio.h>
#include <signal.h>
void sig_usr1(int sig) {
char buf[128];
snprintf(buf, sizeof(buf), "%f", 1.0);
}
int main(int argc, char **argv) {
(void) signal(SIGUSR1, sig_usr1);
while(1);
}
As cnicutar notes, valgrind may have an effect on anything timing related and signal handlers would certainly qualify.
I don't think snprintf is safe to use in a signal handler so it might be working in the non-valgrind case solely by accident and then valgrind comes in, changes the timing, and you get the flaming death that you were risking without valigrind.
I found a list of functions that are safe in signal handlers (according to POSIX.1-2003 ) here:
http://linux.die.net/man/2/signal
Yes, the linux.die.net man pages are a bit out of date but the list here (thanks to RedX for finding this one):
https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers
doesn't mention snprintf either except in the context of OpenBSD where it say:
... asynchronous-safe in OpenBSD but "probably not on other systems," including snprintf(), ...
so the implication is that snprintf is not, in general, safe in a signal handler.
And, thanks to Nemo, we have an authoritative list of functions that are safe for use in signal handlers:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03
Start at that link and search down for _Exit and you'll see the list; then you'll see that snprintf is not on the list.
Also, I remember using write() in a signal handler because fprintf wasn't safe for a signal handler but that was a long time ago.
I don't have a copy of the relevant standard so I can't back this up with anything really authoritative but I thought I'd mention it anyway.
From manual: http://www.network-theory.co.uk/docs/valgrind/valgrind_27.html and http://www.network-theory.co.uk/docs/valgrind/valgrind_24.html
Valgrind's signal simulation is not as robust as it could be. Basic POSIX-compliant sigaction and sigprocmask functionality is supplied, but it's conceivable that things could go badly awry if you do weird things with signals. Workaround: don't. Programs that do non-POSIX signal tricks are in any case inherently unportable, so should be avoided if possible.
So, snprintf in signal handler is not a POSIX-allowed signal trick and valgrind has a right to brick your programs.
Why snprintf is not signal-safe?
The glibc manual says: http://www.gnu.org/software/hello/manual/libc/Nonreentrancy.html
If a function uses and modifies an object that you supply, then it is potentially non-reentrant; two calls can interfere if they use the same object.
This case arises when you do I/O using streams. Suppose that the signal handler prints a message with fprintf. Suppose that the program was in the middle of an fprintf call using the same stream when the signal was delivered. Both the signal handler's message and the program's data could be corrupted, because both calls operate on the same data structure—the stream itself.
However, if you know that the stream that the handler uses cannot possibly be used by the program at a time when signals can arrive, then you are safe. It is no problem if the program uses some other stream.
You can say that s*printf* are not on streams, but on strings. But internally, glibc's snprintf does work on special stream:
ftp://sources.redhat.com/pub/glibc/snapshots/glibc-latest.tar.bz2/glibc-20090518/libio/vsnprintf.c
int
_IO_vsnprintf (string, maxlen, format, args)
{
_IO_strnfile sf; // <<-- FILE*-like descriptor
The %f output code in glibc also has a malloc call inside it:
ftp://sources.redhat.com/pub/glibc/snapshots/glibc-latest.tar.bz2/glibc-20090518/stdio-common/printf_fp.c
/* Allocate buffer for output. We need two more because while rounding
it is possible that we need two more characters in front of all the
other output. If the amount of memory we have to allocate is too
large use `malloc' instead of `alloca'. */
size_t wbuffer_to_alloc = (2 + (size_t) chars_needed) * sizeof (wchar_t);
buffer_malloced = ! __libc_use_alloca (chars_needed * 2 * sizeof (wchar_t));
if (__builtin_expect (buffer_malloced, 0))
{
wbuffer = (wchar_t *) malloc (wbuffer_to_alloc);
if (wbuffer == NULL)
/* Signal an error to the caller. */
return -1;
}
else
wbuffer = (wchar_t *) alloca (wbuffer_to_alloc);
Valgrind slightly changes the timings in your program.
Have a loot at the FAQ.
My program crashes normally, but doesn't under Valgrind, or vice
versa. What's happening?
When a program runs under Valgrind, its environment is slightly
different to when it runs natively.
Most of the time this doesn't make any difference, but it can,
particularly if your program is buggy.
This is a valgrind bug. It calls your signal handler with a stack that is not 16-byte aligned as required by the ABI. On x86_64, floating point arguments are passed in XMM registers which can only be stored at addresses that are 16-byte aligned. You can work around the problem by compiling for 32-bit (gcc -m32).

Resources