Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place! |
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.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
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.
|
|
01-19-2010, 08:16 PM
|
#1
|
LQ Newbie
Registered: Jan 2010
Posts: 5
Rep:
|
Problems designing a signal handler in UNIX
I'm trying to create a signal handler thread to handle SIGALRM signals.
The main thread calls the following function before creating any other threads
Code:
pthread_t Timer::Init(long _clock_interval_musec)
{
// Set interval.
clock_interval = _clock_interval_musec;
// This is called while in a single threaded environment.
// Main thread masks alarm.
sigset_t alarm_off_mask;
if ((sigemptyset(&alarm_off_mask) == -1) || (sigaddset(&alarm_off_mask, SIGALRM) == -1))
perror("Failed to initialize the signal set");
if (pthread_sigmask(SIG_BLOCK, &alarm_off_mask, NULL) == -1)
perror("Failed to block SIGALRM");
// Now call a new thread which handles alarm signals.
pthread_t retID;
pthread_create(&retID, NULL, TimerHandlerThread, NULL);
// Return id of thread responsible for managing alarm signals.
return retID;
}
As you can see, I block the alarm signal.
The spawned signal handler thread has the following Run function
Code:
void* Timer::TimerHandlerThread(void* args)
{
// Change granualirity of alarm.
itimerval tv;
tv.it_interval.tv_sec = clock_interval / USECS_IN_SECS;
tv.it_interval.tv_usec = clock_interval % USECS_IN_SECS;
setitimer(ITIMER_REAL, &tv, NULL);
// Unmask alarm signals in this thread.
sigset_t sigset;
if ((sigemptyset(&sigset) == -1) || (sigaddset(&sigset, SIGALRM) == -1))
perror("Failed to add signal to wait for");
Timer currentTime;
int sig;
while (1)
{
/* wait for a signal to arrive */
sigwait(&sigset, &sig);
std::cout << "we are here\n";
if (sig == SIGALRM && g_timerQueue.size() > 0)
{
currentTime.Set(0);
// Handle if needed
g_mutex.P();
if (*(g_timerQueue.front()) < currentTime)
{
g_timerQueue.front()->Event_Handler();
std::pop_heap(g_timerQueue.begin(), g_timerQueue.end());
g_timerQueue.pop_back();
}
g_mutex.V();
}
}
return NULL;
}
Sigwait never returns ("we are here" never prints).
clock_interval is 50.
Is the timer not firing?
Did I not set my interval correctly?
Did I not proper block the signals ensuring the that the default handler would not take care of them?
Any help is welcome.
|
|
|
01-19-2010, 09:46 PM
|
#2
|
LQ Guru
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,393
|
I'd suggest you ask the mods (via the report button) to move this to the Programming section for better/faster help.
|
|
|
01-20-2010, 01:03 AM
|
#3
|
LQ Newbie
Registered: Jan 2010
Posts: 5
Original Poster
Rep:
|
Quote:
Originally Posted by chrism01
I'd suggest you ask the mods (via the report button) to move this to the Programming section for better/faster help.
|
I wouldn't mind that at all. I just figured the newbie section was proper for me since I've only started reading, nevermind programming, on Unix a week ago. Here is the code as it stands now by the way
Code:
void* Timer::TimerHandlerThread(void* args)
{
// Change granualirity of alarm.
itimerval tv;
tv.it_value.tv_sec = tv.it_interval.tv_sec = clock_interval / USECS_IN_SECS;
tv.it_value.tv_usec = tv.it_interval.tv_usec = clock_interval % USECS_IN_SECS;
if (setitimer(ITIMER_REAL, &tv, NULL) == -1)
perror("Failed to set timer interval");
Timer currentTime;
int sig;
while (1)
{
/* wait for a signal to arrive */
sigwait((const sigset_t*)args, &sig);
if (sig == SIGALRM && g_timerQueue.size() > 0)
{exit(0);
currentTime.Set(0);
// Handle if needed
g_mutex.P();
if (*(g_timerQueue.front()) < currentTime)
{
g_timerQueue.front()->Event_Handler();
std::pop_heap(g_timerQueue.begin(), g_timerQueue.end());
g_timerQueue.pop_back();
}
g_mutex.V();
}
}
return NULL;
}
pthread_t Timer::Init(long _clock_interval_musec)
{
// Set interval.
clock_interval = _clock_interval_musec;
// This is called while in a single threaded environment.
// Main thread masks alarm.
sigset_t sigset;
if (sigemptyset(&sigset) == -1)
perror("Failed to add signal to block");
if (sigaddset(&sigset, SIGALRM) == -1)
perror("Failed to add signal to block");
if (sigprocmask(SIG_BLOCK, &sigset, NULL) == -1)
perror("Failed to block SIGALRM");
// Now call a new thread which handles alarm signals.
pthread_t retID;
pthread_create(&retID, NULL, TimerHandlerThread, (void*)&sigset);
// Return id of thread responsible for managing alarm signals.
return retID;
}
It still gives me simillar problems.
Timer::Init is the first thing called in main.
|
|
|
01-20-2010, 09:01 AM
|
#4
|
Senior Member
Registered: Jan 2005
Location: Melbourne, Australia
Distribution: Debian Bookworm (Fluxbox WM)
Posts: 1,391
|
Quote:
Is the timer not firing?
Did I not set my interval correctly?
Did I not proper block the signals ensuring the that the default handler would not take care of them?
|
I cannot repeat the problem (ie it works here). Perhaps look at the following:
1. print out the values you are storing in the timing counters tv_sec/tv_usec
2. make sure that the main thread is not exiting (since its return will end the program)
3. it isn't clear why you are creating the currentTime object on the stack inside the TimerHandlerThread member function
|
|
|
01-21-2010, 11:58 PM
|
#5
|
LQ Newbie
Registered: Jan 2010
Posts: 5
Original Poster
Rep:
|
Quote:
Originally Posted by neonsignal
I cannot repeat the problem (ie it works here). Perhaps look at the following:
1. print out the values you are storing in the timing counters tv_sec/tv_usec
2. make sure that the main thread is not exiting (since its return will end the program)
3. it isn't clear why you are creating the currentTime object on the stack inside the TimerHandlerThread member function
|
1. They are fine.
2. It's exiting gracefully, the threads run just fine in the background. In fact, the thread runs, it just blocks in sigwait.
3. It doesn't matter.
I implemented the same signal handling technique with sigaction and it works. It's just more writing and less elegant. =/
|
|
|
01-22-2010, 12:15 AM
|
#6
|
Senior Member
Registered: Jan 2005
Location: Melbourne, Australia
Distribution: Debian Bookworm (Fluxbox WM)
Posts: 1,391
|
Quote:
It's exiting gracefully, the threads run just fine in the background
|
My point was that the threads will die if the code exits from main. Since you didn't include that bit of the code, it wasn't clear. It also isn't clear how you have declared the member functions (I'm assuming the thread function must be static).
I have only tested your code under Linux and it works okay (ie, the signal is caught by the sigwait and it reaches the next lines). You might be on a different system (BSD?).
|
|
|
01-23-2010, 06:11 AM
|
#7
|
LQ Newbie
Registered: Jan 2010
Posts: 5
Original Poster
Rep:
|
Quote:
Originally Posted by neonsignal
My point was that the threads will die if the code exits from main. Since you didn't include that bit of the code, it wasn't clear. It also isn't clear how you have declared the member functions (I'm assuming the thread function must be static).
I have only tested your code under Linux and it works okay (ie, the signal is caught by the sigwait and it reaches the next lines). You might be on a different system (BSD?).
|
I was running under BSD first, but I wasn't aware it would have not worked. But like I said... the sigaction "version" works perfectly. =/
I'll try running under Linux.
|
|
|
01-23-2010, 05:08 PM
|
#8
|
Senior Member
Registered: Jan 2005
Location: Melbourne, Australia
Distribution: Debian Bookworm (Fluxbox WM)
Posts: 1,391
|
I suspect that your main code is making use of sleep/usleep. These calls also make use of SIGALRM, which will cause undefined behaviour.
If you use pthread_sigmask instead of sigprocmask (both the main and the handler thread need to block the signal), this may help.
|
|
|
All times are GMT -5. The time now is 05:00 AM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|