This program
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <windows.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
void INThandler(int);
int main(void)
{
signal(SIGINT, INThandler);
char data[128];
int n;
while((n=read(0, data, 128)) > 0)
{
if(data[n] = '\n') break;
}
data[n] ='\0';
printf("%s", data);
return 0;
}
void INThandler(int sig)
{
char c;
signal(sig, SIG_IGN);
printf("OUCH, did you hit Ctrl-C?\n"
"Do you really want to quit? [y/n] ");
c = getchar();
if (c == 'y' || c == 'Y')
exit(0);
else
signal(SIGINT, INThandler);
}
Doesn't handle ctrl-c, but terminates at that input.
If I replace everything between the handler install and the return by
while (1)
Sleep(1);
the handler function is called and works but I want to have the read() in there.
EDIT: Looking back at this program, I noticed that I have
if(data[n] = '\n') break;
I wrote '=' instead of '==', but by using the later, it doesn't work properly and I don't understand why. Shouldn't it be a comparison to detect '\n'?
Also, I messed around with the buffer, but I can't make keep the input if I hit CTRL-C.
The example code does not take into accounts two issues:
read() will abort it's work if its process receives a signal (see man 2 read)
It is only guaranteed for a few functions that they can be called savely from a signal handler function (see man 7 signal). printf()and getch() do not not belong to this set of "save" functions.
The first issue could be fixed using a more differentiated way to handle the value returned by read(). I should counts how much data had already been read, together with some smart adjustment of the buffer passed to read().
Regarding the second issue, read() and write() are the functions of choice to perform input/output to/from a signal handler as those are listed to be "save" functions by the man-page mentioned above.
It's because of the implementation of read(2) you use doesn't allow that. Here is what I get when I compile your program, execute it and press ^C:
$ ./program
^COUCH, did you hit Ctrl-C?
Do you really want to quit? [y/n] y
$
or if I answer n and enter some data:
$ ./program
^COUCH, did you hit Ctrl-C?
Do you really want to quit? [y/n] n
test
test
$
Since read(2) is a system call, it depends on the system you use. I use Linux (3.2.0-4-686-pae) and here it's behaving correctly. Maybe you should consider to use scanf(3) or fread(3) with stdio(3) instead, for the platform you're using (which I take to be win32)? Or also use a different implementation, like the ones from Cygwin or MinGW?
Related
I have this very basic shell program that just keeps prompting for an input until user presses control+c.
I am trying to configure the SIGTSTP signal's handler function to display a message and not terminate the program.
(SIGTSTP is triggered by control+z and by default terminates the program and all child processes.)
The problem: As soon as I press control+z, which triggers the SIGTSTP signal, the program crashes.
Below is my code which includes my basic shell program and my attempt to define the custom handler function for SIGTSTP.
Thank you for any help and suggestions!
#define _GNU_SOURCE
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdbool.h>
#include <sys/types.h>
#include <signal.h>
void handle_SIGTSTP(int signo){
char* message = "\ncontrol + z pressed\n";
write(STDOUT_FILENO, message, 21);
fflush(stdout);
};
int main() {
struct sigaction SIGTSTP_custom = {0};
SIGTSTP_custom.sa_handler = handle_SIGTSTP;
sigaction(SIGTSTP, &SIGTSTP_custom, NULL);
while(true) {
char *user_input = malloc(200);
memset(user_input, '\0', 200);
size_t max_input_size = 199;
printf("enter input: ");
fflush(stdout);
getline(&user_input, &max_input_size, stdin);
};
return 0;
};
You need to pass the SA_RESTART flag to the sigaction structure:
...
struct sigaction SIGTSTP_custom = {0};
SIGTSTP_custom.sa_flags |= SA_RESTART; // add this
SIGTSTP_custom.sa_handler = handle_SIGTSTP;
sigaction(SIGTSTP, &SIGTSTP_custom, NULL);
...
The behavior of the signal handler will depend on those flags, information on all flags is available on the man page (man sigaction).
Pablo found your main bug: you need to set the SA_RESTART flag to have interrupted system calls restarted.
When SIGTSTP arrives, your program is presumably waiting for I/O in getline, with a system call such as read(2). Without SA_RESTART, this system call fails when the signal arrives, and sets errno to EINTR. The failure of read() causes getline to set the error flag on stdin, which makes all successive getline calls fail immediately, and puts you in an infinite loop of printf.
If you had checked the return value from getline() and done proper error reporting, it would have helped you find this.
The infinite loop by itself wouldn't make your program crash, but you have another bug: you allocate memory on every iteration of the loop, and then leak it. You really want to declare and initialize user_input and max_input_size outside your loop. You also don't need to allocate memory yourself; you can let getline() do it the first time by initializing to NULL and 0. The usual idiom for getline would look like:
char *user_input = NULL;
size_t max_input_size = 0;
while (getline(&user_input, &max_input_size, stdin) != -1) {
// do stuff with user_input
}
// either error or EOF, handle appropriately
free(user_input);
And one more bug: it's not safe to call fflush or other stdio functions in a signal handler. It's also not necessary because the write() doesn't go through the stdio buffers anyway.
I am trying to allow an interrupt to cause a certain value to be returned by readline. Here is a minimal example:
#include <stdio.h>
#include <signal.h>
#include <readline/readline.h>
void handler (int status)
{
rl_replace_line("word",0);
rl_redisplay();
rl_done = 1;
}
int main (int argc, char** argv)
{
char* entry;
signal(SIGINT,handler);
entry = readline("");
printf("\nEntry was: %s\n", entry);
return 0;
}
If I run this code and press Control-C, after I hit ENTER, sure enough it prints "Entry was: word". But I would like it to do so without the user needing to press ENTER. I basically just want to set entry to "word" when the interrupt signal is received, ending the readline function. I have been unable to find any documentation for how to just end the readline loop and return a certain value (I'm sure it's out there, but I haven't found it).
One thing I tried was adding
(*rl_named_function("accept-line"))(1,0);
at the end of handler, but it didn't send the text to "entry" immediately.
I think I have what you want running here.
#include <stdio.h>
#include <signal.h>
#include <readline/readline.h>
int event(void) { }
void handler (int status)
{
rl_replace_line("word",0);
rl_redisplay();
rl_done = 1;
}
int main (int argc, char** argv)
{
char* entry;
rl_event_hook=event;
signal(SIGINT,handler);
entry = readline("");
printf("\nEntry was: %s\n", entry);
return 0;
}
The secret is the rl_done is only checked in the event loop. When you give it a null event hook function, it checks the rl_done and exits.
I don't believe there is any guarantee that you can call back into readline functions from an asynchronous signal handler. (The fact that it "seems to" work does not guarantee that it will not fail disastrously from time to time.) In general, you should do the absolute minimum in a signal handler, such as setting a flag to indicate that the signal has been received.
The readline library provides the variable rl_signal_event_hook, whose value is a function which will be called when a readline call is interrupted by a signal. It would probably be wise to put any code which modifies the readline state into such a function.
But it seems like the safest solution here would be to arrange for the Control-C character to be passed directly to readline without triggering a SIGINT. You could create a custom terminal setting based on the termios struct returned by tcgetattr which turns off the mapping of Ctrl-C to the INTR function, either by unsetting the ISIG flag (which will also turn off other interrupt characters, including Ctrl-Z) or by changing c_cc[VINTR] to _POSIX_VDISABLE (or to some other key).
If you are on Windows and you are not using Cygwin, which includes termios emulation, you can use native APIs to enable and disable Control-C handling.
Then you can use rl_bind_key to bind Ctrl-C (which is 3) to your own function. The function needs to match the rl_command_func_t typedef, which is int(*)(int, int). The function should return 0; in your simple case, you can probably ignore the arguments, but for the record the first one is a "count" (the numeric argument, entered by typing a number while holding down the Alt key), and the second one is the key itself.
You should probably make a copy of the termios structure before you modify it so that you can reset the terminal settings once you're done. Generally, you would want to install and restore the terminal settings around every call to readline (which is what readline itself does, as well).
CTRL+C should pass a SIGINT, or similar interrupt signal to your program. There should be ways to override the handling, see here for example.
You can achieve this by using the alternate interface, where your code is doing the event loop and calls libreadline functions each time a character needs to be read from the terminal. In the event loop you can handle all extra asynchronous events like signals (but not only that --- think a terminal chat application where messages arrive asynchronously from the network).
Here's how it could look like:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <readline/readline.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
static volatile sig_atomic_t my_signal_flag = 0;
static int done_loop = 0;
void my_signal_handler (int status)
{
my_signal_flag = 1; // set a volaatile sig-atomic_t var
// and exit, just as the standard says
}
void my_rlhandler(char* line) // all your app is in this function
// called each time a line is ready
{
if (line && strcmp(line, "quit"))
printf("Entry was: %s\n", line);
else
{
done_loop = 1;
rl_set_prompt("");
}
free(line);
}
void my_event_loop() // event loop
// handle all async events here
// signals, network, threads, whatever
{
rl_callback_handler_install("w00t>", my_rlhandler);
do
{
signal(SIGINT, my_signal_handler); // readline may override this
// better do it here each time
fd_set readfds; // prepare the select
FD_ZERO(&readfds);
FD_SET(0, &readfds);
if (select(1, &readfds, NULL, NULL, NULL) > 0)
{
rl_callback_read_char(); // character ready, let readline eat it
}
else if (my_signal_flag )
{
my_signal_flag = 0; // can get here only after a signal
rl_replace_line("word",0);
rl_done = 1;
rl_redisplay();
rl_pending_input = '\n'; // not sure why it's needed
rl_callback_read_char();
}
}
while (!done_loop);
rl_callback_handler_remove();
}
int main (int argc, char** argv)
{
char* entry;
signal(SIGINT, my_signal_handler);
my_event_loop();
return 0;
}
While this may seem more complicated that other methods, the callback interface is more appropriate for real-life programs that need to handle a variety of events.
I have a very strange problem in C. A function from a proprietary library reduces sleep(n) to sleep(0).
My code looks like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /*sleep() */
int main(int argc, char** argv){
//...
AStreamEngine.init();
AStreamEngine.setCodec(3);
AStreamEngine.start(); //problematic function
printf("a");
sleep(100);
printf("b");
return 0;
}
If the problematic function is commented out, then printing "a" follows by printing "b" after 100 sec. But if isn't commented out, "ab" is printed. So the program ends very quickly and I cannot notice if the engine works.
I found that:
if I replace sleep() by getchar() the engine works correctly.
if I put active waiting by a for-loop then it also works.
Does anyone have any idea why happens? And how to fix (bypass) this feature/bug? I don't want use getchar and active waiting.
Update:
I don't have source of the library. I have only binary .so file.
Base on responces I add a below code add end:
struct timespec to_sleep = { 1, 0 };
int ret = nanosleep(&to_sleep,&to_sleep);
printf("%d\n",ret);
if(ret == -1){
printf(" break sleep : %d %s", errno,strerror(errno));
}
And I get output:
-1
break sleep : 4 Interrupted system callc
Now I try to bypass by thread.
"sleep" can be interrupted by signals - see http://man7.org/linux/man-pages/man3/sleep.3.html . My guess is that the "start" function started a thread which might have caused signals to be sent to your program. Put "sleep" in a loop like this:
unsigned int x = 100;
while (x > 0) { x = sleep (x); }
Another point: printf may be line-buffered. In that mode, the output is only seen if you print a "\n" character. Try using "a\n".
As rightly said by Jack, usleep and sleep can be interrupted by the delivery of signals (E.g presence of ioctl, read, write function calls).
One of the smart way to avoid this issue is to use nanosleep. Like sleep and usleep, nanosleep can also be interrupted by the delivery of signals but the difference is, its second argument tells you how much time is remaining.
You can use this argument to make sure your code sleeps for the specified amount of time. Replace your sleep and usleep function with a while loop containing nanosleep. Following is the example usage,
struct timespec to_sleep = { 1, 0 }; // Sleep for 1 second
while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
Off course this solutions is not suitable for the application where exact amount sleep is required but it is very useful in the cases where minimum delay is required before executing next function.
After examination, I think that the using of the sleep() function is useless on your case.
Indeed, the sleep function uses the pause() function, which wait for a signal and stops if your process receive a signal call.
In your case it's probably the problem, and it explains why the sleep() function stops when you call the AStreamEngine.start() function.
I think that the best solution is to use the usleep() function, which should not stops if your process receive a signal.
Try this :
usleep(VALUE_IN_MILISECONDS);
Good luck ! :)
How can I exit from an infinite loop, when a key is pressed?
Currently I'm using getch, but it will start blocking my loop as soon, as there is no more input to read.
If you are using getch() from conio.h anyway, try to use kbhit() instead. Note that both getch() and kbhit() - conio.h, in fact - are not standard C.
The function kbhit() from conio.h returns non-zero value if any key is pressed but it does not block like getch(). Now, this is obviously not standard. But as you are already using getch() from conio.h, I think your compiler has this.
if (kbhit()) {
// keyboard pressed
}
From Wikipedia,
conio.h is a C header file used in old MS-DOS compilers to create text user interfaces. It is not described in The C Programming Language book, and it is not part of the C standard library, ISO C nor is it required by POSIX.
Most C compilers that target DOS, Windows 3.x, Phar Lap, DOSX, OS/2, or Win321 have this header and supply the associated library functions in the default C library. Most C compilers that target UNIX and Linux do not have this header and do not supply the library functions.
I would suggest that you go throgh this article.
Non-blocking user input in loop without ncurses.
If you do not want to use non-standard, non-blocking way and yet graceful exit. Use signals and Ctrl+C with user provided signal handler to clean up. Something like this:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
/* Signal Handler for SIGINT */
void sigint_handler(int sig_num)
{
/* Reset handler to catch SIGINT next time.
Refer http://en.cppreference.com/w/c/program/signal */
printf("\n User provided signal handler for Ctrl+C \n");
/* Do a graceful cleanup of the program like: free memory/resources/etc and exit */
exit(0);
}
int main ()
{
signal(SIGINT, sigint_handler);
/* Infinite loop */
while(1)
{
printf("Inside program logic loop\n");
}
return 0;
}
// Include stdlib.h to execute exit function
int char ch;
int i;
clrscr();
void main(){
printf("Print 1 to 5 again and again");
while(1){
for(i=1;i<=5;i++)
printf("\n%d",i);
ch=getch();
if(ch=='Q')// Q for Quit
exit(0);
}//while loop ends here
getch();
}
I'm practicing C programming for Linux for an exam.
I don't know how to exit the program when user press Ctrl + a ( not Ctrl+c )
For example, looping something until user press Ctrl+a
Could anyone tell me how to check Ctrl+a input?
Notes: I'm using 'gcc' and run output with './a.out'
Thanks in advance for everyone!
Turbo C and other implementations of C for Windows had a function call getch() which would read single characters from the keyboard; those would have done what you want.
In POSIX environments, such as are implemented by gcc-compiled programs under Unix/Linux, that functionality isn't directly there.
There's a library called curses which allows C programs to do full-screen output processing, and there is also getch() functionality in curses. This may end up being the simplest answer to your problem. You'll need to read the documentation on curses and link the header files and library into your program.
There is special support for Ctrl-C, which is translated into a signal by the system. If you want your program to stop as soon as another specific key combination is used, it will be much harder.
you will need to check the standard input of your program, and you will need to set the standard input so the inputs are not buffered (otherwise you won't see any input until it is validated by the user pressing "return"). The latter part would be done with a ioctl() call and would not be portable;
you will need either threads or polling, none of which is very palatable in C.
There are more interesting things to practice in C than these.
catching ctrl-c event
This post answers your question
did you looking for something like this ???
this program won't be stopped since you hit ctrl+A and Enter.
#include <stdio.h>
int main() {
char a;
while( a!=1 ) //Ascii code for ctrl + A == 1
{
a=getchar();
printf("still looping ...\n");
}
printf( "HA! You pressed CTRL+A\n" );
return 0;
}
But if you wanna terminate your program just after pressing ctrl+A (without hitting enter after that), here you are:
#include <stdio.h>
#include <ncurses.h>
int main() {
char a;
initscr();
raw();
while( a!=1 )
a=getch();
endwin();
return 0;
}
for compiling second code using GCC, try this command:
gcc -o program.o -lncurses program.cpp
This will do what you want:
stty intr ^a
./a.out
For extra credit, do the equivalent of "stty intr ^a" using the appropriate library function, e.g. "man termios".
Someone posted first with following code which works for me but I don't know why he deleted his answer.
Original Link : http://www.c.happycodings.com/Gnu-Linux/code18.html
#include <stdio.h>
#include <unistd.h> /* sleep(1) */
#include <signal.h>
void ex_program(int sig);
int main(void) {
(void) signal(SIGINT, ex_program);
while(1)
printf("sleeping .. ZZZzzzz ....\n"), sleep(1);
return 0;
}
void ex_program(int sig) {
printf("Wake up call ... !!! - Catched signal: %d ... !!\n", sig);
(void) signal(SIGINT, SIG_DFL);
}
This is how to set CTRL-A as interrupt to break the process. Notice too that CTRL-C doesn't break it after tcsetattr is called.
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
struct termios termios;
if ( tcgetattr(0, &termios) != -1 ) {
termios.c_cc[VINTR] = '\x01'; /* CTRL-A */
if ( tcsetattr(0, 0, &termios) != -1 ) {
printf("Ready. Press CTRL-A to break this program\n");
while ( 1 ) {
printf("*\n");
sleep(1);
}
}
}
}