Assign a specific sighandler to a signal - c

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?

Related

Save data about signal in file?

I am trying to save certain information about the signal in a file, e.g. time it was caught, etc, in the signal handler.
void sig_handler(int signo){
curr_signal = time(NULL);
receivedtime[z] = curr_signal;
signumber = signo;
diff = curr_signal - receivedtime[z-1];
z++;
write(f, &diff, sizeof(diff));
}
I have updated my program to write inside the file (f). My problem is that nothing is being written inside the file.The file is being created.
Be careful about the calls from inside your signal handler.
From man 7 signal:
Async-signal-safe functions
A signal handler function must be very careful, since processing else‐
where may be interrupted at some arbitrary point in the execution of
the program. POSIX has the concept of "safe function". If a signal
interrupts the execution of an unsafe function, and handler either
calls an unsafe function [...],
then the behavior of the program is undefined.
And follows a list of the functions that are async-signal-safe.
Your signal handler calls:
time(): ok, it is async-signal-safe
fprintf(): nope, it is not.
The existing answer tells you why it doesn't work: you call signal-unsafe functions in your signal handler. I want to add what to do instead: it's best practice to do as little as possible inside the handler and instead inform your "normal" code about the signal. This can be done using a volatile sig_atomic_t variable. Just update your data structures and set a volatile sig_atomic_t to 1. In your main code, check that variable periodically, and if it is set, do the desired output and set it back to 0.

Suspending thread execution within signal handler

This is a bit of a follow-up to this question.
Suppose I use sigaction to set up a signal handler of my own design. In this signal handler, I access information about the CPU state (the thread's stack pointer, for example) and copy it to a predetermined location in memory. I now want to examine a value on this thread's stack from another thread.
Is there a way to suspend execution of the thread in the signal handler from within the same signal handler, so that I can safely examine this thread's stack from another thread? (Note: I define "safely" here to mean "without worrying about the thread completing or returning from a function.)
If I was outside of the signal handler, I could use sigsupend; however, it's not safe to use within the signal handler according to the GNU documentation. I could also try extending a signal using the method described in this question, but I don't think any of the standard *nix signals will help me here.
A blocking read on a pipe is async-signal-safe, and provides a convenient way to wake up your "suspended" thread.
E.g.,
static int the_pipe[2] = {-1, -1}; // file descriptors allocated in main via pipe()
static void
siginfo_handler(int s, siginfo_t *si, void *ctx) {
char c;
// do something with (ucontext_t *)ctx
// now wait for someone else to wake us up
read(the_pipe[0], &c, 1);
...
}

When I catch a signal with signal(SIGINT,f), is f executed in parallel?

I have C code like this
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void handler_function(int);
int i=0;
int j=0;
int main() {
signal(SIGINT,f);
while(1) {
/* do something in variable `i` */
}
}
void f(int signum) {
/* do something else on variable `i` */
}
Can it produce a data race? i.e. is f executed in parallel (even in a multithread machine) to the main. Or maybe is the main stopped until f finish its execution?
First of all according to the man page of signal() you should not use signal() but sigaction()
The behavior of signal() varies across UNIX versions, and has also varied historically across different versions of Linux. Avoid its use: use sigaction(2) instead. See Portability below.
But one might hope that signal() behaves sanely. However, there might be a data race because main might be interrupted before a store e.g. in a situation like this
if ( i > 10 ) {
i += j;
}
void f(int signum) {
i = 0;
}
If main is past the compare (or if the according registers do not get update if main was interrupted while compare), main would still to i += j which is a data race.
So where does this leave us? - Don't ever modify globals that get modified elsewhere in signal handlers if you cannot guarantee that the signal handler cannot interrupt this operation (e.g. disable signal handler for certain operations).
Unless you use the raise() from Standard C or kill() with the value from getpid() as the PID argument, signal events are asynchronous.
In single-threaded code on a multi-core machine, it means that you cannot tell what is happening in the 'do something to variable i' code. For example, that code might have just fetched the value from i and have incremented it, but not yet saved the incremented value. If the signal handler function f() reads i, modifies it in a different way, saves the result and returns, the original code may now write the incremented value of i instead of using the value modified by f().
This is what leads to the many constraints on what you can do in a signal handler. For example, it is not safe to call printf() in a signal handler because it might need to do memory allocation (malloc()) and yet the signal might have arrived while malloc() was modifying its linked lists of available memory. The second call to malloc() might get thoroughly confused.
So, even in a single-threaded program, you have to be aware and very careful about how you modify global variables.
However, in a single-threaded program, there will be no activity from the main loop while the signal is being handled. Indeed, even in a multi-threaded program, the thread that receives (handles) the signal is suspended while the signal handler is running, but other threads are not suspeded so there could be concurrent activity from other threads. If it matters, make sure the access to the variables is properly serialized.
See also:
What is the difference between sigaction() and signal()?
Signal concepts.

Providing/passing argument to signal handler

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)

How can I know the current state of signals

Is there a way in C to know the following information about signals:
Is certain signal is blocked now?
Are we inside a signal handling function chanin (i.e, was the current code called from function which was called as signal handler for certain signal)? If so, can I know what is the current signal?
Thanks
You can know which signals are currently blocked by calling sigprocmask with second argument null and third argument non-null (the first argument is ignored under these conditions, so pass zero). It'll fill in the sigset_t you provide as the third argument.
I'm not aware of any way to know whether there is a signal handler frame on the stack. I suppose you might be able to use the _Unwind_* family of functions somehow but it would be a horrible kludge.
Firstly, you can use sigprocmask with an empty set pointer.
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
a. how can be set to:
SIG_UNBLOCK (the signal in set are removed from the current set of blocked signals. It is legal to attempt to unblock signal which is not blocked)
b. set can be set to NULL (as you don't want to change the blocked signals)
c. If oldset is not NULL, the previous value of the signal mask is stored in oldset. Ergo, you get the blocked signals in the location whose address is stored in oldset.
Secondly, for knowing if you are in a signal handling routine, when you write the signal handler definition, you can accept int signum as a parameter, as in:
void mySignalHandler(int signum);
If you want to know so that you can block some other signals at that point of time, you could just have a blocking function at the start & unblocking function at the end (using sigprocmask()). You could even set said signals to SIG_IGN status to ignore them while handling the current signal (using signal() ).
Lastly, please read the man pages!
Edit:
Since the author says he does read them, I recommend using the apropos command to find such hard-to-find functions. For example,
$ apropos "blocked signals"
gives you around 5 hits, 1 of which is sigprocmask
Cheers!

Resources