ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
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.
But the problem is that there is no way of passing a user input to the signal handler.
Most people solve this problem using semaphores. Try "man -k semaphore". You can also use a pthread_mutex, but you have to include libpthread when you build your executable.
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:
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.
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.
You can use the "void pointer" to pass any pointer and cast it to a user defined type in the signal handler.
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.
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.
I don’t understand. How do you expect to provide “user input” to a signal which is automatically generated? What kind of input do you want to provide? Can we see some sample code?
Quote:
Originally Posted by David1357
You can use the "void pointer" to pass any pointer and cast it to a user defined type in the signal handler.
I don’t think the user has any control over the contents of the context pointer (it is set by the kernel and holds the instruction address of where the process was interrupted by the signal).
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.
I think i did not get the problem statement right. I will tell the original problem.
Now that we know what you are trying to do, we can recommend a better solution. Use a pthread to check for expiration of a timer then call the callback function for the timer. Most of the time, this pthread will be doing usleep(1) or something similar, so it should not be very resource intensive until it calls a timer callback.
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.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.