Can I use fprintf(stderr) in a signal (SIGALRM) handler with glibc/linux?
No you cannot. Check the manpage signal(7) for a list of async-signal-safe functions. fprintf is not included in that list.
If you don't need formatting then you can use write(STDERR_FILENO, <buf>, <buflen>) to write to stderr.
This is not safe, quoting IBM DeveloperWorks article about Signal Handling Safety
Suppose the signal handler prints a message with fprintf and 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.
Related
This is similar to the question 1 but is about pipes. If epoll_wait returns EPOLLERR for the write end of a pipe, how do I distinguish a general error condition from the read end of the pipe been closed? For the sockets case the answer was to use "use getsockopt and SO_ERROR to get the pending error" and compare that with EPIPE. But what API should I use for the pipe as the pipe created by pipe(2) on Linux or returned by opening a named pipe is not a socket?
Other than the other end being closed, there aren't any errors on a write end of a pipe which could be detected by epoll. The few errors that are possible on an actual call to write() could not be known in advance (e.g., if you pass an invalid buffer pointer), so epoll cannot detect them. Therefore, if epoll tells you there's an error, it is EPIPE.
(OK, there is actually another possible error condition, but it can be triggered only by a programming error: if you close the file descriptor and then use epoll_wait while it is on the list - I don't know how epoll will react to that).
SUSv4 does not list opendir, readdir, closedir, etc. in its list of async-signal-safe functions.
Is there a safe way to read a directory listing from a signal handler?
e.g. is it possible to 'open' the directory and somehow slurp out the raw directory listing? If so what kind of data structure is returned by 'read'?
Or maybe on Linux there are certain system calls that are async-signal-safe even though SUSv4 / POSIX does not require it that could be used?
If you know in advance which directory you need to read, you could call opendir() outside the signal handler (opendir() calls malloc(), so you can't run it from within the handler) and keep the DIR* in a static variable somewhere. When your signal handler runs, you should be able to get away with calling readdir_r() on that handle as long as you can guarantee that only that one signal handler would use the DIR* handle at any moment. There is a lock field in the DIR that is taken by readdir() and readdir_r(), so if, say, you used the DIR* from two signal handlers, or you registered the same handler to handle multiple signals, you may end up with a deadlock due to the lock never being released by the interrupted handler.
A similar approach appears to also work to read a directory from a child process after calling fork() but before calling execve().
!/usr/bin/env perl
use POSIX;
my $sig_set = POSIX::SigSet->new(POSIX::SIGINT);
my $sig_act = POSIX::SigAction->new(sub { print "called\n"; exit 0 },$sig_set);
POSIX::sigaction(SIGINT,$sig_act);
sleep(15);
Why do I need to use POSIX::SigSet if I already tell POSIX::sigaction that I want SIGINT?
Basically I'm trying to respond with my coderef to each of the signal I add to SigSet, looking at POSIX::sigaction signature, it must accept a singal as the first parametner, which doesnt seems reasonable to be if I already tell POSIX::SigAction about my POSIX::SigSet.
I'm sure I am missing something here.
thanks,
The answer to your question
The POSIX::SigSet specifies additional signals to mask off (to ignore) during the execution of your signal handler sub. It corresponds to the sa_mask member of the underlying struct passed to the C version of sigaction.
Now, SIGINT (well, the first argument to sigaction) will be masked off by default, unless you explicitly request otherwise via the SA_NODEFER.
A better approach?
However, if all you want to do it to register a signal handler whose execution won't be interrupted by the signal for which it was registered (e.g., don't allow SIGINT during your SIGINT handler), you can skip the POSIX module entirely:
$SIG{INT} = sub { print "called\n"; exit 0; }; # Won't be interrupted by SIGINT
Where it can, Perl's signal dispatching emulates the traditional UNIX semantics of blocking a signal during its handler execution. (And on Linux, it certainly can. sigprocmask() is called before executing the handler, and then a scope-guard function is registered to re-allow that signal at the end of the user-supplied sub.)
Question:
When a process is killed, is this information recorded anywhere (i.e., in kernel), such as syslog (or can be configured to be recorded syslog.conf)
Is the information of the killer's PID, time and date when killed and reason
update - you have all giving me some insight, thank you very much|
If your Linux kernel is compiled with the process accounting (CONFIG_BSD_PROCESS_ACT) option enabled, you can start recording process accounting info using the accton(8) command and use sa(8) to access the recorded info. The recorded information includes the 32 bit exit code which includes the signal number.
(This stuff is not widely known / used these days, but I still remember it from the days of 4.x Bsd on VAXes ...)
Amended:
In short, the OS kernel does not care if the process is killed. That is dependant on whether the process logs anything. All the kernel cares about at this stage is reclaiming memory. But read on, on how to catch it and log it...
As per caf and Stephen C's mention on their comments...
If you are running BSD accounting daemon module in the kernel, everything gets logged. Thanks to Stephen C for pointing this out! I did not realize that functionality as I have this switched off/disabled.
In my hindsight, as per caf's comment - the two signals that cannot be caught are SIGKILL and SIGSTOP, and also the fact that I mentioned atexit, and I described in the code, that should have been exit(0);..ooops Thanks caf!
Original
The best way to catch the kill signal is you need to use a signal handler to handle a few signals , not just SIGKILL on its own will suffice, SIGABRT (abort), SIGQUIT (terminal program quit), SIGSTOP and SIGHUP (hangup). Those signals together is what would catch the command kill on the command line. The signal handler can then log the information stored in /var/log/messages (environment dependant or Linux distribution dependant). For further reference, see here.
Also, see here for an example of how to use a signal handler using the sigaction function.
Also it would be a good idea to adopt the usage of atexit function, then when the code exits at runtime, the runtime will execute the last function before returning back to the command line. Reference for atexit is here.
When the C function exit is used, and executed, the atexit function will execute the function pointer where applied as in the example below. - Thanks caf for this!
An example usage of atexit as shown:
#include <stdlib.h>
int main(int argc, char **argv){
atexit(myexitfunc); /* Beginning, immediately right after declaration(s) */
/* Rest of code */
return 0;
exit(0);
}
int myexitfunc(void){
fprintf(stdout, "Goodbye cruel world...\n");
}
Hope this helps,
Best regards,
Tom.
I don't know of any logging of signals sent to processes, unless the OOM killer is doing it.
If you're writing your own program you can catch the kill signal and write to a logfile before actually dying. This doesn't work with kill -9 though, just the normal kill.
You can see some details over thisaway.
If you use sudo, it will be logged. Other than that, the killed process can log some information (unless it's being terminated with extreme prejudice). You could even hack the kernel to log signals.
As for recording the reason a process was killed, I've yet to see a psychic program.
Kernel hacking is not for the weak of heart, but hella fun. You'd need to patch the signal dispatch routines to log information using printk(9) when kill(3), sigsend(2) or the like is called. Read "The Linux Signals Handling Model" for more information on how signals are handled.
If the process is getting it via kill(2), then unless the process is already logging the only external trace would be a kernel mod. It's pretty simple; just do a printk(), it's like printf(). Find the output in dmesg.
If the process is getting it via /bin/kill, then it would be a relatively easy matter to install a wrapper executable that did logging. But this (signal delivery via /bin/kill) is unlikely because kill is also a bash built-in.
By the way, if a process is killed with a signal is announced by the kernel to the parent process via de wait(2) system call. The value returned by this call is the exit status of the child (the lower byte) and some signal related info in the upper byte in case this process has been killed. See wait(2) for more information.
i am using message queue as an ipc between 2 programs.
Now i want to send data from one program to another using message queue and then intimate it through a signal SIGINT.
I dont know how to send a signal from one program to another .
Can anybody pls provide a sample code if they have the solution.
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
Signal in linux can be send using kill system call just check this link for documentation of kill system call and example. you can see man -2 kill also. and it's not advisable to use SIGINT use SIGUSR1 or SIGUSR2
Note that by using the sigqueue() system call, you can pass an extra piece of data along with your signal. Here's a brief quote from "man 2 sigqueue":
The value argument is used to specify
an accompanying item of data (either
an integer or a pointer value) to be
sent
with the signal, and has the following type:
union sigval {
int sival_int;
void *sival_ptr;
};
This is a very convenient way to pass a small bit of information between 2 processes. I agree with the user above -- use SIGUSR1 or SIGUSR2 and a good sigval, and you can pass whatever you'd like.
You could also pass a pointer to some object in shared memory via the sival_ptr, and pass a larger object that way.
system("kill -2 `pidof <app_name_here>` ");