Providing/passing argument to signal handler - c

Can I provide/pass any arguments to signal handler?
/* Signal handling */
struct sigaction act;
act.sa_handler = signal_handler;
/* some more settings */
Now, handler looks like this:
void signal_handler(int signo) {
/* some code */
}
If I want to do something special i.e. delete temp files, can I provide those files as an argument to this handler?
Edit 0: Thanks for the answers. We generally avoid/discourage use of global variables. And in this case, If you have a huge program, things can go wrong at different places and you might need to do a lot of cleanup. Why was the API designed this way?

You can't have data of your own passed to the signal handler as parameters. Instead you'll have to store your parameters in global variables. (And be really, really careful if you ever need to change those data after installing the the signal handler).
Response to edit 0: Historical reasons. Signals are a really old and really low-level design. Basically you're just given the kernel a single address to some machine code and asking it to go to this specific address if such and such happens. We're back in the "portable assembler" mindset here, where the kernels provide a no-frills baseline service, and whatever the user process can reasonably be expected to to for itself, it must do itself.
Also, the usual arguments against global variables don't really apply here. The signal handler itself is a global setting, so there is no relevant possibility of having several different sets of user-specified parameters for it around. (Well, actually it is not entirely global but only thread-global. But the threading API will include some mechanism for thread-local storage, which is just what you need in this case).

A signal handler registration is already a global state equivalent to global variables. So it's no greater offense to use global variables to pass arguments to it. However, it's a huge mistake (almost certainly undefined behavior unless you're an expert!) to do anything from a signal handler anyway. If you instead just block signals and poll for them from your main program loop, you can avoid all these issues.

This is a really old question but I think I can show you a nice trick that would have answered your problem.
No need to use sigqueue or whatever.
I also dislike the use of globals variables so I had to find a clever way, in my case, to send a void ptr (which you can later cast to whatever suits your need).
Actually you can do this :
signal(SIGWHATEVER, (void (*)(int))sighandler); // Yes it works ! Even with -Wall -Wextra -Werror using gcc
Then your sighandler would look like this :
int sighandler(const int signal, void *ptr) // Actually void can be replaced with anything you want , MAGIC !
You might ask : How to get the *ptr then ?
Here's how :
At initialization
signal(SIGWHATEVER, (void (*)(int))sighandler)
sighandler(FAKE_SIGNAL, your_ptr);
In your sighandler func
:
int sighandler(const int signal, void *ptr)
{
static my_struct saved = NULL;
if (saved == NULL)
saved = ptr;
if (signal == SIGNALWHATEVER)
// DO YOUR STUFF OR FREE YOUR PTR
return (0);
}

Absolutely. You can pass integers and pointers to signal handlers by using sigqueue() instead of the usual kill().
http://man7.org/linux/man-pages/man2/sigqueue.2.html

Store the names of the files in a global variable and then access it from the handler. The signal handler callback will only be passed one argument: the ID for the actual signal that caused the problem (eg SIGINT, SIGTSTP)
Edit 0: "There must be a rock solid reason for not allowing arguments to the handler." <-- There is an interrupt vector (basically, a set of jump addresses to routines for each possible signal). Given the way that the interrupt is triggered, based on the interrupt vector, a particular function is called. Unfortunately, it's not clear where the memory associated with the variable will be called, and depending on the interrupt that memory may actually be corrupted. There is a way to get around it, but then you can't leverage the existing int 0x80 assembly instruction (which some systems still use)

I think you it's better to use SA_SIGINFO in sa_flags so the handler will get
void signal_handler(int sig, siginfo_t *info, void *secret)
in siginfo_t you can provide your params.
Ty:HAPPY code

You can use a signal handler which is a method of a class. Then that handler can access member data from that class. I'm not entirely sure what Python does under the covers here around the C signal() call, but it must be re-scoping data?
I was amazed that this works, but it does. Run this and then kill the process from another terminal.
import os, signal, time
class someclass:
def __init__(self):
self.myvalue = "something initialized not globally defined"
signal.signal(signal.SIGTERM, self.myHandler)
def myHandler(self, s, f):
# WTF u can do this?
print "HEY I CAUGHT IT, AND CHECK THIS OUT", self.myvalue
print "Making an object"
a = someclass()
while 1:
print "sleeping. Kill me now."
time.sleep(60)

Related

Assign a specific sighandler to a signal

I have a question concerning signals in C. I want to assign some a specific sighandler to a signal.
My function is:
void searchOccurences(char **myString, char chr, int *occurences) {
/* I perform some search actions here
* at the end of this function *occurrence will contain the
* the number occurrences of chr in myString*/
}
I want to assign this function to the SIGILL signal (i.e Illegal Instruction Signal), but I can't because the __sighandler_t handlers are of this kind of definition:
typedef void (*__sighandler_t) (int);
So How can I assign my function to this signal? What are the alternative solutions to what I want to do?
Thanks :)
Don't use SIGILL, that could mask a genuine error. SIGUSR1 and SIGUSR2 are specifically for user defined signals.
You can't pass additional information, sorry, but there it is. The best you can do is to store information in a global before raising a signal, but you must be certain of the sequence of events, or use some sort of synchronisation like a mutex.
By the way, are you aware that many C runtime library functions are not signal safe?

A function that use global variable but exit, should still be avoided in signal handlers ?

As I studied something about unix programming with C, I've learned that functions that fails to be reentrant should be avoided inside a signal handler, but if I've something like:
int main(int argc, char** argv){
...
fileFd=open(...)
signal(SIGUSR1, signalHandler)
...
}
void signalHandler(int signo){
switch(signo){
case SIGUSR1:
myExit(EXIT_FAILURE);
break;
default:
break;
}
}
Where myExit is
void myExit(int ret){
...DO STUFF...
close(fileFd);
exit(ret);
}
and fileFd is a global variable, and if I remember correctly that makes of myExit a non-reentrant... but it's still a problem to use it in a signal handler even if it will cause the exit of the program ?
Thanks, any help is appreciated and sorry if it's a dumb question.
The only thing you can do safely in a signal handler is to set a volatile sig_atomic_t variable. Please do all your handling in the main loop of your program by checking that a signal has been received (outside of the signal handler). If you do have to start doing non-portable things then consider at least using _Exit() or _exit(). Certain C libraries will guarantee that certain functions are signal-safe but this is not guaranteed to work on different systems obviously.
It might get a problem depending on "...DO STUFF...". If the stuff done there may not be done twice (like freeing the same pointer), it could crash.
In your particular case however this will probably not be a problem, if close(fileFD) is the only thing affecting global state and your file access API allows double-closing of files.
Still not safe if you use any async-unsafe functions. An asynchronous signal like USR1 can occur between any two instructions in your program, including in the middle of a critical section (locked section) in some library code.
So, for example, if the interruption happens in the middle of malloc, calling free in your signal handler (e.g. to clean up) will deadlock.

Catching Segmentation Violations and Getting on with Life

I'm writing a program that's examining its own address space.
Specifically, I care about all malloc-ed data blocks. If there some system call to get a list of them, that would be fantastic (for my application, I cannot use LD_PRELOAD, -wrap, nor any extra command line options). If there's a way to do this, I'd love to hear it even more than an answer to my stated problem, below.
In lieu of this, my current approach is to just dereference everything and look around. Obviously, the set of all possible pointers is a minefield of segfaults waiting to happen, so I tried registering a signal handler and using setjmp/longjmp (simply ignoring the segfault by making the handler do nothing is an infinite loop because the handler will return to the faulting instruction). Some example code goes like so:
static jmp_buf buf;
void handler(int i) {
printf(" Segfaulted!\n");
longjmp(buf,-1);
}
void segfault(void) {
int* x = 0x0;
int y = *x;
}
void test_function(void) {
signal(11,handler);
while (1) {
if (setjmp(buf)==0) {
printf("Segfaulting:\n");
segfault();
}
else {
printf("Recovered and not segfaulting!\n");
}
printf("\n");
}
}
The output is:
Segfaulting:
Segfaulted!
Recovered and not segfaulting!
Segfaulting:
Segmentation fault
So, the handler didn't work the second time around. I don't know why this is, but I speculated it had something to do with not clearing the original signal. I don't know how to do that.
As an aside, I tried sigsetjmp/siglongjmp first, but they weren't defined for some reason in setjmp.h. I got vague vibes that one needed to pass some extra compile flags, but, as before, that is not allowed for this application.
The system being used is Ubuntu Linux 10.04 x86-64, and any solution does not need to be portable.
[EDIT: sigrelse in the handler clears the signal, and fixes the problem effectively. Question now concerns the other issues raised--is there a better way (i.e., get the blocks of malloc)? What's up with sigsetjmp/siglongjmp? Why do I need to reset the signal?]
signal() is a legacy interface, and may or may not re-register a signal handler after it has been invoked, depending on the OS; you may need to issue another signal() call to reset the signal handler as the last action in your handler. See man 2 signal.
sigaction() is the preferred mechanism to set signal handlers, as it has well defined and portable behavior.
When the signal handler for SIGSEGV is invoked, the SIGSEGV signal will be masked as if by sigprocmask. This is true for any signal. Normally returning from the signal handler would unmask it, but since you're not returning, that never happens. There are a couple possible solutions:
You can call sigprocmask either before or after the longjmp to unmask it yourself.
You can install the signal handler with sigaction (the preferred way to do it anyway) and use the SA_NODEFER flag to prevent it from being masked.
You can use the sigsetjmp and siglongjmp functions, which themselves take responsibility for saving and restoring the signal mask.

Reading registers or thread local variables of another thread

Is it possible to read the registers or thread local variables of another thread directly, that is, without requiring to go to the kernel? What is the best way to do so?
You can't read the registers, which wouldn't be useful anyway. But reading thread local variables from another thread is easily possible.
Depending on the architecture (e. g. strong memory ordering like on x86_64) you can safely do it even without synchronization, provided that the read value doesn't affect in any way the thread is belongs to. A scenario would be displaying a thread local counter or similar.
Specifically in linux on x86_64 as you tagged, you could to it like that:
// A thread local variable. GCC extension, but since C++11 actually part of C++
__thread int some_tl_var;
// The pointer to thread local. In itself NOT thread local, as it will be
// read from the outside world.
struct thread_data {
int *psome_tl_var;
...
};
// the function started by pthread_create. THe pointer needs to be initialized
// here, and NOT when the storage for the objects used by the thread is allocated
// (otherwise it would point to the thread local of the controlling thread)
void thread_run(void* pdata) {
pdata->psome_tl_var = &some_tl_var;
// Now do some work...
// ...
}
void start_threads() {
...
thread_data other_thread_data[NTHREADS];
for (int i=0; i<NTHREADS; ++i) {
pthread_create(pthreadid, NULL, thread_run, &other_thread_data[i]);
}
// Now you can access each some_tl_var as
int value = *(other_thread_data[i].psome_tl_var);
...
}
I used similar for displaying some statistics about worker threads. It is even easier in C++, if you create objects around your threads, just make the pointer to the thread local a field in your thread class and access is with a member function.
Disclaimer: This is non portable, but it works on x86_64, linux, gcc and may work on other platforms too.
There's no way to do it without involving the kernel, and in fact I don't think it could be meaningful to read them anyway without some sort of synchronization. If you don't want to use ptrace (which is ugly and non-portable) you could instead choose one of the realtime signals to use for a "send me your registers/TLS" message. The rough idea is:
Lock a global mutex for the request.
Store the information on what data you want (e.g. a pthread_key_t or a special value meaning registers) from the thread in global variables.
Signal the target thread with pthread_kill.
In the signal handler (which should have been installed with sigaction and SA_SIGINFO) use the third void * argument to the signal handler (which really points to a ucontext_t) to copy that ucontext_t to the global variable used to communicate back to the requesting thread. This will give it all the register values, and a lot more. Note that TLS is a bit more tricky since pthread_getspecific is not async-signal-safe and technically not legal to run in this context...but it probably works in practice.
The signal handler posts a semaphore (this is the ONLY async-signal-safe synchronization function offered by POSIX) indicating to the requesting thread that it's done, and returns.
The requesting thread finishes by waiting on the semaphore, then reads the data and unlocks the request mutex.
Note that this will involve at least 1 transition to kernelspace (pthread_kill) in the requesting thread (and maybe another in sem_wait), and 1-3 in the target thread (1 for returning from the signal handler, one for entering the signal handler if it was not already sleeping in kernelspace, and possibly one for sem_post). Still it's probably faster than mucking around with ptrace which is not designed for high-performance usage...

Issue in sighandler

I am creating a user level thread library implementing preemptive round robin scheduler. I have the handler function like this:
void handler(int signum)
{
gtthread_yield();
}
In the gtthread_yield, i am doing the context switching to switch to the next thread to be executed. The logic works fine in most cases. But, i am getting a segmentation fault when the signal is raised even before the gtthread_yield function (called from sighandler) could finish executing. Because of this , my code accesses invalid memory location (memory that i had already freed)
Is there any way to avoid handler being raised before the gtthread_yield function finishes execution?
Thanks
Use sigaction() and its helpers (sigemptyset(), sigfillset(), sigaddset(), etc.) to block signals while the handler is in progress. That is probably a necessary step; it may not be sufficient. If it is not sufficient, you probably need to revise the signal handling so that it does almost nothing except a volatile sig_atomic_t variable before returning. Then the calling code has to look at the atomic variable and call gtthread_yield() when it is set (remembering to clear the variable after returning from gtthread_yield().
You can block other signals for the handler duration, see e.g. this entry in glibc manual how to do it.

Resources