LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
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


Reply
  Search this Thread
Old 01-19-2010, 08:16 PM   #1
19bernardo87
LQ Newbie
 
Registered: Jan 2010
Posts: 5

Rep: Reputation: 0
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.
 
Old 01-19-2010, 09:46 PM   #2
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,369

Rep: Reputation: 2753Reputation: 2753Reputation: 2753Reputation: 2753Reputation: 2753Reputation: 2753Reputation: 2753Reputation: 2753Reputation: 2753Reputation: 2753Reputation: 2753
I'd suggest you ask the mods (via the report button) to move this to the Programming section for better/faster help.
 
Old 01-20-2010, 01:03 AM   #3
19bernardo87
LQ Newbie
 
Registered: Jan 2010
Posts: 5

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by chrism01 View Post
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.
 
Old 01-20-2010, 09:01 AM   #4
neonsignal
Senior Member
 
Registered: Jan 2005
Location: Melbourne, Australia
Distribution: Debian Bookworm (Fluxbox WM)
Posts: 1,391
Blog Entries: 54

Rep: Reputation: 360Reputation: 360Reputation: 360Reputation: 360
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
 
Old 01-21-2010, 11:58 PM   #5
19bernardo87
LQ Newbie
 
Registered: Jan 2010
Posts: 5

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by neonsignal View Post
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. =/
 
Old 01-22-2010, 12:15 AM   #6
neonsignal
Senior Member
 
Registered: Jan 2005
Location: Melbourne, Australia
Distribution: Debian Bookworm (Fluxbox WM)
Posts: 1,391
Blog Entries: 54

Rep: Reputation: 360Reputation: 360Reputation: 360Reputation: 360
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?).
 
Old 01-23-2010, 06:11 AM   #7
19bernardo87
LQ Newbie
 
Registered: Jan 2010
Posts: 5

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by neonsignal View Post
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.
 
Old 01-23-2010, 05:08 PM   #8
neonsignal
Senior Member
 
Registered: Jan 2005
Location: Melbourne, Australia
Distribution: Debian Bookworm (Fluxbox WM)
Posts: 1,391
Blog Entries: 54

Rep: Reputation: 360Reputation: 360Reputation: 360Reputation: 360
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.
 
  


Reply



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
user-define signal handler & coredump for signal 11(SIGSEGV) Alexlun Linux - Software 2 05-24-2009 06:37 AM
How to reinstall a signal handler after exec ( Strange behaviour in signal handling ) lali.p Programming 0 09-20-2008 12:11 PM
Is it valid to do semop in signal handler ? pravinsd Linux - Kernel 3 07-16-2008 08:49 AM
signal handler routine vdx Programming 7 09-24-2007 12:43 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 07:26 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
Open Source Consulting | Domain Registration