How to pass input to a signal handler ?
Hi all,
Iam using uclibc on uclinux and writing a timer application (where on expiry of timer, a user specified signal is generated). The possible signal handlers are void func(int signal) and void func(int signo ,siginfo_t* pInfo,void* context) depending whether or not SA_SIGINFO is reset ot not. But the problem is that there is no way of passing a user input to the signal handler. Any way of achieving this ? Vasanth |
The only way to do that would be assigning he user input to a global variable. But this can easily cause hard to solve problems, even if you're fully aware of all the dangers.
The thing with signals is that they really can occur any moment. Suppose the user input is short string: then a signal can occur even in the middle of writing the string to memory. In that case your signal handler is called when the string is half written and does not yet have a '\0' terminator! That would cause strange behaviour of your program once in 10 times, or once in 100 times, who knows... Whether, and how often, this will occur may even depend on things like the kernel version. One way to solve this is to have a handler that only sets a global flag indicating that a (or which) signal was catched. The in the main loop of the program he flag is regularly checked, and then handled inside the normal program flow. That way you can use the variable containg the user input the normal way. The global flag need to be so small that the operating system can garantee that it will be set in one single CPU instruction. On many systems a single <int> will do. The header files for the operating system will typedef the apropriate type for this to "sig_atomic_t". So it is safest to use that as the type for your global flag variable. Here's avery simple example of this mechanism: Code:
#include <stdio.h> |
Quote:
|
I am unsure of uclinux, but in linux (and any POSIX operating system which supports the “realtime signals extension” to the POSIX standard), you can use sigqueue() to send a sigval along with a signal. You will need to use the second form of signal handler, and the value will be available as:
Code:
pInfo->si_value.sival_int |
The issue with using sigqueue is that the,In my case,signal is generated automatically on expiration of a timer. Otherwise that would have been a good solution.
The signal handlers at most give signal number, other signal info(through siginfo_t*) and user context (a void pointer).It looks like there is no provision for providing user input to signal handler. Any more inputs are welcome. Vasanth |
Quote:
You can use shared data (using the method suggested by Hko) or protected by a semaphore (as suggested by me). There are plenty of ways to pass user input to a signal handler. I think you are misreading the responses to your post. |
Quote:
Quote:
|
Hi,
I think i did not get the problem statement right. I will tell the original problem. I am writing a C++ wrapper class for the software timer to support some legacy code written using proprietary OS. So, each object of that class(timer class) will represent a timer.And the user will be providing a user defined function(void (*)(void*)) and a void* input to that function. So each object of the timer will be having a separate timer function and input. Glibc provides a functionality regarding timer where a timer function and a user specified input can be provided while creating a timer.(which will be run on expiration of the timer). It also provides another facility where a signal can be generated on expiration of the timer. Unfortunately, uclibc(which iam using) supports only the second method only(signals). Since its wriiten in C++, the signal handling mechanism has to be dealt internally inside the class.(user need not know the internal implementation). So if i make the signal handler as my class method, I cannot pass it to Linux as the method signatures will not match. i.e int func (int,siginfo_t*,void* context) Vs int (Timer::*)(int,siginfo_t,void* context) So, i had to make the signal handler static. (I cannot even cast them) So, the core question is that how do i call the user provided function along with its input from inside a class static signal handler. One solution is using global variables,but its not practical for me. If there was any way of passing input to the signal (generated on expiration of POSIX timer), then i could have used a void* to pass the address of my object,using which i can call user provided timer function inside my class static signal handler.{As static function can only call other static/global functions and static variables and user provided timer function will be different for each object) Hope this give a clearer picture regarding my original question. Vasanth |
Quote:
You can pass a pointer to the list of timers using the "void *arg" parameter of pthread_create. This gets you around the problem of using a global variable. The only optimization you might want to make is to spawn a separate each time the timer thread calls a callback function so that the timer thread does not block on a callback. |
All times are GMT -5. The time now is 10:59 PM. |