I am working on an assignment where I am implementing the unix history command in a shell. In my program I have written a signal handler for SIGINT. When a user enters (ctrl)(c) their history is displayed.
When my program terminates I need to store the history in a file. Is there an easy way to detect when my program has exited? Or do I need to have a signal handler for every type of signal ((ctrl)(d), pausebreak, etc).
atexit() is probably what you're looking for, see the manual page: man 3 atexit
Usage is something like:
#include <stdlib.h>
static void save_the_file(void)
{
/* ... */
}
int main()
{
atexit(save_the_file);
return 0;
}
Another option is to use the destructor attribute (GCC/Clang):
static __attribute__((destructor)) void save_the_file(void)
{
/* your code */
}
atexit is that. But if you want to follow SIGKILL also, you need watcher-process that call waitpid().
Related
Some time ago I found this exercise in C: without changing the main function, so that receiving a SIGUSR1 signal output is directed and added to a file in append mode as the first parameter. At the reception of another SIGUSR1 the output is directed to the console, and so on. How do such an exercise?
#include <stdio.h>
#include <time.h>
void redirectsetup (char *s){
}
int main (int argc, char *argv[]){
redirect setup(argv[1]);
while(1){
time_t now = time(NULL);
printf("%s",ctime(&now));
sleep(1);
}
}
I'll give you some general pointers.
You need to install a signal handler. Try typing man signal or googling "signal handler linux". As a rule your signal handler should do the minimum possible, many things are illegal in signal handlers including much of the C library. In this case, you could have it set a variable which tells you where to direct output and leave it at that.
Your main program needs to loop, sending characters to wherever the variable tells it.
One thing you might need to be careful of is a signal interrupting a system call, requiring it to be retried.
Have a go and see if you can make it work.
All,
I want to develop an exit handler in my program.
I'm really new to C; is it all about managing signals in C?
How do I know if my program ended in a good way or not?
If not, how do I get the maximum information when exiting?
C (C89 and C99 standards) provides atexit() to register function to be called when the program exits. This has nothing to do with signals. Unlike signal handlers, you can register multiple exit handlers. The exit handlers are called in reverse order of how they were registered with atexit().
The convention is that when program exits cleanly it returns exit status 0. This can be done by return 0 from main() or exit(0) from anywhere in your program.
In Unix/Linux/POSIX type operating system (not sure of Windows), the parent process get exit status information about the child process using wait() system call or its variants.
Example: Here is a simple program and its output to demonstrate atexit():
#include <stdlib.h>
#include <stdio.h>
static void exit_handler1(void)
{
printf("Inside exit_handler1()!n");
}
static void exit_handler2(void)
{
printf("Inside exit_handler2()!n");
}
int main(int argc, char *argv[])
{
atexit(exit_handler1);
atexit(exit_handler2);
return 0;
}
Output generated by the program:
Inside exit_handler2()!
Inside exit_handler1()!
Look here you will find all what you want:
http://www.cplusplus.com/reference/cstdlib/exit/
I added a new link here take a look:
Exception libraries for C (not C++)
If i am not get wrong you ask about giving back results from program when exiting. You should use exit(x); function to return value from your program. You can put any integer value as parameter x. And dont forget to use #include <stdlib.h> in your program start.
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.
While learning signal() system call, I supposed to come across the following code,
#include <stdio.h>
#include <signal.h>
void sigproc(int);
void quitproc(int);
int main(int argc,char **argv)
{
signal(SIGINT, sigproc); //Is it like a normal Call to signal()?
signal(SIGQUIT, quitproc);// This too?
printf("ctrl- c disabled use ctrl\ to quit \n");
while(1);
return 0;
}
void sigproc(int signo)
{
printf("you have pressed ctrl - c \n");
}
void quitproc(int signo)
{
printf("U cant quit\n");
// exit(0);
}
I am calling the function signal() twice in main(). But its executed only when I'm pressing Ctrl-C and Ctrl-\ keys. I thought its also like normal function call. What is actually happening in the signal handler functions?
The signal function establishes a signal handler. What it means: "When my process receives this signal, run this function instead of doing whatever the default was".
So, in your example the calls to signal don't call the function. To actually see the signals in action, do this:
Start your process in one terminal
From another terminal:
kill -INT `pidof proc`
As a side note, printf and friends aren't async-signal-safe. It might come as a shocker, but it's unsafe to use them in signal handlers.
As a side side note, even if you tagged your question Unix it's important to know that signals (and the signal function) are standard, integral parts of C. Signal handling and the signal function are described in C99 in ยง7.14.1.
The example code of section 10.6, the expected result is:
after several iterations, the static structure used by getpwnam will be corrupted, and the program will terminate with SIGSEGV signal.
But on my platform, Fedora 11, gcc (GCC) 4.4.0, the result is
[Langzi#Freedom apue]$ ./corrupt
in sig_alarm
I can see the output from sig_alarm only once, and the program seems hung up for some reason, but it does exist, and still running.
But when I try to use gdb to run the program, it seems OK, I will see the output from sig_alarm at regular intervals.
And from my manual, it said the signal handler will be set to SIG_DEF after the signal is handled, and system will not block the signal. So at the beginning of my signal handler I reset the signal handler.
Maybe I should use sigaction instead, but I only want to know the reason about the difference between normal running and gdb running.
Any advice and help will be appreciated.
following is my code:
#include "apue.h"
#include <pwd.h>
void sig_alarm(int signo);
int main()
{
struct passwd *pwdptr;
signal(SIGALRM, sig_alarm);
alarm(1);
for(;;) {
if ((pwdptr = getpwnam("Zhijin")) == NULL)
err_sys("getpwnam error");
if (strcmp("Zhijin", pwdptr->pw_name) != 0) {
printf("data corrupted, pw_name: %s\n", pwdptr->pw_name);
}
}
}
void sig_alarm(int signo)
{
signal(SIGALRM, sig_alarm);
struct passwd *rootptr;
printf("in sig_alarm\n");
if ((rootptr = getpwnam("root")) == NULL)
err_sys("getpwnam error");
alarm(1);
}
According to the standard, you're really not allowed to do much in a signal handler. All you are guaranteed to be able to do in the signal-handling function, without causing undefined behavior, is to call signal, and to assign a value to a volatile static object of the type sig_atomic_t.
The first few times I ran this program, on Ubuntu Linux, it looked like your call to alarm in the signal handler didn't work, so the loop in main just kept running after the first alarm. When I tried it later, the program ran the signal handler a few times, and then hung. All this is consistent with undefined behavior: the program fails, sometimes, and in various more or less interesting ways.
It is not uncommon for programs that have undefined behavior to work differently in the debugger. The debugger is a different environment, and your program and data could for example be laid out in memory in a different way, so errors can manifest themselves in a different way, or not at all.
I got the program to work by adding a variable:
volatile sig_atomic_t got_interrupt = 0;
And then I changed your signal handler to this very simple one:
void sig_alarm(int signo) {
got_interrupt = 1;
}
And then I inserted the actual work into the infinite loop in main:
if (got_interrupt) {
got_interrupt = 0;
signal(SIGALRM, sig_alarm);
struct passwd *rootptr;
printf("in sig_alarm\n");
if ((rootptr = getpwnam("root")) == NULL)
perror("getpwnam error");
alarm(1);
}
I think the "apue" you mention is the book "Advanced Programming in the UNIX Environment", which I don't have here, so I don't know if the purpose of this example is to show that you shouldn't mess around with things inside of a signal handler, or just that signals can cause problems by interrupting the normal work of the program.
According to the spec, the function getpwnam is not reentrant and is not guaranteed to be thread safe. Since you are accessing the structure in two different threads of control (signal handlers are effectively running in a different thread context), you are running into this issue. Whenever you have concurrent or parallel execution (as when using pthreads or when using a signal handler), you must be sure not to modify shared state (e.g. the structure owned by 'getpwnam'), and if you do, then appropriate locking/synchronization must be used.
Additionally, the signal function has been deprecated in favor of the sigaction function. In order to ensure portable behavior when registering signal handlers, you should always use the sigaction invocation.
Using the sigaction function, you can use the SA_RESETHAND flag to reset the default handler. You can also use the sigprocmask function to enable/disable the delivery of signals without modifying their handlers.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void sigalrm_handler(int);
int main()
{
signal(SIGALRM, sigalrm_handler);
alarm(3);
while(1)
{
}
return 0;
}
void sigalrm_handler(int sign)
{
printf("I am alive. Catch the sigalrm %d!\n",sign);
alarm(3);
}
For example, my code is runing in main doing nothing and every 3 seconds my program says im alive x)
I think that if you do as i done calling in the handler function alarm with value 3, the problem is resolved :)