LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-27-2008, 11:11 AM   #1
vasanth2001
LQ Newbie
 
Registered: Aug 2008
Posts: 6

Rep: Reputation: 0
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
 
Old 08-27-2008, 12:12 PM   #2
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 110Reputation: 110
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>
#include <unistd.h>
#include <signal.h>

sig_atomic_t volatile done = 0;

void handler(int num)
{
    done = 1;
}

int main(void)
{
    signal(SIGALRM, handler);
    alarm(10);

    while (!done)
        puts("Hello World");

    return 0;
}

Last edited by Hko; 08-27-2008 at 12:13 PM.
 
Old 08-27-2008, 01:00 PM   #3
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,302
Blog Entries: 1

Rep: Reputation: 107Reputation: 107
Quote:
Originally Posted by vasanth2001 View Post
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.
 
Old 08-27-2008, 01:41 PM   #4
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 77
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
 
Old 08-28-2008, 03:59 AM   #5
vasanth2001
LQ Newbie
 
Registered: Aug 2008
Posts: 6

Original Poster
Rep: Reputation: 0
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
 
Old 08-28-2008, 08:08 AM   #6
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,302
Blog Entries: 1

Rep: Reputation: 107Reputation: 107
Quote:
Originally Posted by vasanth2001 View Post
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.
 
Old 08-28-2008, 02:49 PM   #7
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 77
Quote:
Originally Posted by vasanth2001 View 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 View Post
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).
 
Old 08-28-2008, 11:10 PM   #8
vasanth2001
LQ Newbie
 
Registered: Aug 2008
Posts: 6

Original Poster
Rep: Reputation: 0
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
 
Old 08-29-2008, 08:50 AM   #9
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,302
Blog Entries: 1

Rep: Reputation: 107Reputation: 107
Quote:
Originally Posted by vasanth2001 View Post
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.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Is it valid to do semop in signal handler ? pravinsd Linux - Kernel 3 07-16-2008 08:49 AM
signal SIGINT handler SOMETIMES doesn't exit Peterius Programming 3 05-25-2008 11:55 PM
signal handler routine vdx Programming 7 09-24-2007 12:43 AM
howto know whether a function is called in signal handler snowing Programming 1 11-07-2005 09:55 PM
Konqueror / KDE Crash Handler: Signal 11 Bob P Linux - Software 4 10-13-2004 04:21 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:25 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration