reacting to two signals sent to the CPU in linux - linux

I wrote the following code:
void handler (int signal) {
if (signal==SIGVTALRM) {
printf("one second passed\n");
}
if (signal==SIGALRM) {
alarm(1);
//printf("curret context is %ld\n" , thread_tbl[currThreadNum].uc.uc_mcontext.cr2);
currThreadNum=(currThreadNum+1)%THREAD_NUM;
printf("switching from thread #%d to thread #%d\n", ((currThreadNum-1+THREAD_NUM)%THREAD_NUM), currThreadNum);
printf("current thread number is %d\n", currThreadNum);
thread_tbl[(currThreadNum-1+THREAD_NUM)%THREAD_NUM].vtime=+1000;
swapcontext( &(thread_tbl[ (currThreadNum-1+THREAD_NUM)%THREAD_NUM ].uc), &(thread_tbl[currThreadNum ].uc) );
}
}
int ut_start(void) {
int i=0;
struct sigaction sa;
struct itimerval itv;
// set the signal
sa.sa_flags=SA_RESTART;
sigfillset(&sa.sa_mask);
sa.sa_handler = handler;
itv.it_interval.tv_sec=0;
itv.it_interval.tv_usec=100;
itv.it_value=itv.it_interval;
if (sigaction(SIGALRM, &sa, NULL)<0) {
abort();
}
if (sigaction(SIGVTALRM, &sa, NULL)<0) {
abort();
}
setitimer(ITIMER_VIRTUAL, &itv, NULL);
for(i=0; i<TAB_SIZE; i++) {
getcontext(&thread_tbl[i].uc); // get the context the content of current thread
makecontext(&thread_tbl[i].uc, (void(*)(void))func ,1, i); // when this context is activated, func will be executed and then uc.uc_link will get control
}
//start running
alarm(1);
currThreadNum=0;
//printf("currThreadNum=0\n");
swapcontext(&temp_context, &thread_tbl[0].uc);
}
My purpose was to write a program that responds to both SIGVTALRM signal and SIGALRM. However, when I run the program, it seems that the program only react to SIGALRM signals.
In the function ut_start() I started a timer that resets every 100 usec. I don't see any evidence that it works.
One more thing, how can debug this program so I can actually see the timer has started? Is there any variable that I can see in debug mode that tells me something about the status of the timer?

I think I found the answer by myself.
The functions I supplies are only a part of my program. Somewhere in the program, I used the function sleep().
According to the documentation of sleep (http://linux.die.net/man/3/sleep):
sleep() may be implemented using SIGALRM; mixing calls to alarm(2) and
sleep() is a bad idea.Using longjmp(3) from a signal handler or
modifying the handling of SIGALRM while sleeping will cause undefined
results.
When I removed the sleep() function, everything was OK.

Related

How many ways will a process be terminated in Linux?

I'm reading Advanced Programming in the Unix Environment 3rd Edn, §7.3, Process Termination, the following statement make me confused:
There are eight ways for a process to terminate. Normal termination
occurs in five ways:
Return from main
Calling exit
Calling _exit or _Exit
Return of the last thread from its start routine (Section 11.5)
Calling pthread_exit (Section 11.5) from the last thread
for
Return of the last thread from its start routine (Section 11.5)
Calling pthread_exit (Section 11.5) from the last thread
I don't think a process will terminate if it is not returned form main function even though the last thread in this process is terminated, am I right? If not, why 4 and 5 are right?
The main thread is one of the threads. For example, in
void *start(void *arg) {
sleep(1);
pthread_exit(0);
}
int main() {
pthread_t t;
pthread_create(&t, 0, start, 0);
pthread_exit(0);
}
the main thread exits immediately, but the process continues running until the last thread has exited. This is true the other way around,
void *start(void *arg) {
pthread_exit(0);
}
int main() {
pthread_t t;
pthread_create(&t, 0, start, 0);
sleep(1);
pthread_exit(0);
}
where the main thread is the last one left.

Does poll/epoll handling is in interrupt context?

This is probably trivial question for some people, but somehow I'm not sure about it.
When waiting with poll for event from kernel, is it that the handling of new event is done in interrupt context ?
If not, does it mean we can sleep/wait (using other commands in handler) in the handler ?
int main (void)
{
struct pollfd fds[2];
int ret;
fds[0].fd = FILENO;
fds[0].events = POLLIN;
fds[1].fd = FILENO;
fds[1].events = POLLOUT;
ret = poll(fds, 2, TIMEOUT * 1000);
if (ret == -1) {
perror ("poll");
return 1;
}
if (!ret) {
return 0;
}
if (fds[0].revents & POLLIN)
{
/********** HANDLING EVENTS HERE ***************/
printf ("FILENO is POLLIN\n");
}
if (fds[1].revents & POLLOUT)
{
/********** HANDLING EVENTS HERE ***************/
printf ("FILENO is POLLOUT\n");
}
return 0;
}
Thank you,
Ran
No (in general).
When you call poll(), the processor context switches to a kernel context, and other processes (and kernel threads) run. Your process will be context switched back in at some point after at least one of your FDs is ready. In general (consider for instance a pipe), interrupt context is not required for this, though note some I/O requires interrupt context to happen (not directly connected to poll()).

GTK+ Thread safety

I'm trying to use threads to manage several things in GTK+, however, as soon as I try to use any GUI function in the new thread, it locks up the GUI and this makes sense since GTK+ is not thread safe. Is there anyway around this?
Here's my code:
int main(int argc, char *argv[])
{
GError *error = NULL;
/* init threads */
g_thread_init(NULL);
gdk_threads_init();
/* init gtk */
gtk_init(&argc, &argv);
....
//Multithreaded functions
g_thread_create(argument_thread, (gpointer)label7, FALSE, &error );
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
return 0;
}
void *argument_thread(void *args)
{
while(1)
{
gdk_threads_enter();
gtk_entry_set_text(entry2,"random stuff");
gdk_threads_leave();
}
}
Not sure if this could be an issue (don't know GTK) but maybe there is a race condition if the thread acquires the lock before the gtk_main has started.
Then you could try:
gdk_threads_enter();
//Multithreaded functions
g_thread_create(argument_thread, (gpointer)label7, FALSE, &error );
gtk_main();
gdk_threads_leave();
Moreover you should temporize your loop:
void *argument_thread(void *args)
{
while(1)
{
gdk_threads_enter();
gtk_entry_set_text(entry2,"random stuff");
gdk_threads_leave();
sleep(10);
}
}
I have resolved the problem using g_timeout e gthread:http://www.freemedialab.org/wiki/doku.php?id=programmazione:gtk:gtk_e_i_thread
Basically I use 3 functions, one that launches the thread, one that does the job without manipulating widgets (thread) and a third type that serves as a timeout timer checking every n seconds certain values ​​written by the thread and updates the ' graphic interface.
Or you can use "g_idle_add" : http://www.freemedialab.org/wiki/doku.php?id=programmazione:gtk:gtk_e_i_thread#versione_con_g_idle_add
gdk_threads_enter() and gdk_threads_leave() are deprecated from 3.6 version of Gtk.

Can't get my thread to execute with SetEvent and WaitForSingleObject

I'm trying to create a thread and let it run until my main signals it to start, which I think is done with SetEvent. But the code in the thread is never executed. Below is the bare code I have stripped down of (I think) unrelated functions. Is the algorithm correct ?
Here is what I thought it did :
When in the main, the thread is created, which means it'll run in the background. When the event is set (SetEvent), the thread picks it up at WaitForSingleObject and then execute the code in the thread, right ?
HANDLE hThread;
HANDLE Event;
DWORD Thread()
{
while(1)
{
wait = WaitForSingleObject(Event, INFINITE)
//This is where I want to execute something
}
}
int _tmain()
{
DWORD dw;
int i;
Event = CreateEvent(NULL,false,false,NULL);
hThread = CreateThread(NULL,0,Thread,EventA,0,NULL);
while(1)
{
if (condition is correct)
{
SetEvent(Event);
}
CloseHandle(Thread);
CloseHandle(Event);
}
return 0;
}
Thanks for having read.
Move CloseHandle lines out of the while loop.

In pthread, how to reliably pass signal to another thread?

I'm trying to write a simple thread pool program in pthread. However, it seems that pthread_cond_signal doesn't block, which creates a problem. For example, let's say I have a "producer-consumer" program:
pthread_cond_t my_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t my_cond_m = PTHREAD_MUTEX_INITIALIZER;
void * liberator(void * arg)
{
// XXX make sure he is ready to be freed
sleep(1);
pthread_mutex_lock(&my_cond_m);
pthread_cond_signal(&my_cond);
pthread_mutex_unlock(&my_cond_m);
return NULL;
}
int main()
{
pthread_t t1;
pthread_create(&t1, NULL, liberator, NULL);
// XXX Don't take too long to get ready. Otherwise I'll miss
// the wake up call forever
//sleep(3);
pthread_mutex_lock(&my_cond_m);
pthread_cond_wait(&my_cond, &my_cond_m);
pthread_mutex_unlock(&my_cond_m);
pthread_join(t1, NULL);
return 0;
}
As described in the two XXX marks, if I take away the sleep calls, then main() may stall because it has missed the wake up call from liberator(). Of course, sleep isn't a very robust way to ensure that either.
In real life situation, this would be a worker thread telling the manager thread that it is ready for work, or the manager thread announcing that new work is available.
How would you do this reliably in pthread?
Elaboration
#Borealid's answer kind of works, but his explanation of the problem could be better. I suggest anyone looking at this question to read the discussion in the comments to understand what's going on.
In particular, I myself would amend his answer and code example like this, to make this clearer. (Since Borealid's original answer, while compiled and worked, confused me a lot)
// In main
pthread_mutex_lock(&my_cond_m);
// If the flag is not set, it means liberator has not
// been run yet. I'll wait for him through pthread's signaling
// mechanism
// If it _is_ set, it means liberator has been run. I'll simply
// skip waiting since I've already synchronized. I don't need to
// use pthread's signaling mechanism
if(!flag) pthread_cond_wait(&my_cond, &my_cond_m);
pthread_mutex_unlock(&my_cond_m);
// In liberator thread
pthread_mutex_lock(&my_cond_m);
// Signal anyone who's sleeping. If no one is sleeping yet,
// they should check this flag which indicates I have already
// sent the signal. This is needed because pthread's signals
// is not like a message queue -- a sent signal is lost if
// nobody's waiting for a condition when it's sent.
// You can think of this flag as a "persistent" signal
flag = 1;
pthread_cond_signal(&my_cond);
pthread_mutex_unlock(&my_cond_m);
Use a synchronization variable.
In main:
pthread_mutex_lock(&my_cond_m);
while (!flag) {
pthread_cond_wait(&my_cond, &my_cond_m);
}
pthread_mutex_unlock(&my_cond_m);
In the thread:
pthread_mutex_lock(&my_cond_m);
flag = 1;
pthread_cond_broadcast(&my_cond);
pthread_mutex_unlock(&my_cond_m);
For a producer-consumer problem, this would be the consumer sleeping when the buffer is empty, and the producer sleeping when it is full. Remember to acquire the lock before accessing the global variable.
I found out the solution here. For me, the tricky bit to understand the problem is that:
Producers and consumers must be able to communicate both ways. Either way is not enough.
This two-way communication can be packed into one pthread condition.
To illustrate, the blog post mentioned above demonstrated that this is actually meaningful and desirable behavior:
pthread_mutex_lock(&cond_mutex);
pthread_cond_broadcast(&cond):
pthread_cond_wait(&cond, &cond_mutex);
pthread_mutex_unlock(&cond_mutex);
The idea is that if both the producers and consumers employ this logic, it will be safe for either of them to be sleeping first, since the each will be able to wake the other role up. Put it in another way, in a typical producer-consumer sceanrio -- if a consumer needs to sleep, it's because a producer needs to wake up, and vice versa. Packing this logic in a single pthread condition makes sense.
Of course, the above code has the unintended behavior that a worker thread will also wake up another sleeping worker thread when it actually just wants to wake the producer. This can be solved by a simple variable check as #Borealid suggested:
while(!work_available) pthread_cond_wait(&cond, &cond_mutex);
Upon a worker broadcast, all worker threads will be awaken, but one-by-one (because of the implicit mutex locking in pthread_cond_wait). Since one of the worker threads will consume the work (setting work_available back to false), when other worker threads awake and actually get to work, the work will be unavailable so the worker will sleep again.
Here's some commented code I tested, for anyone interested:
// gcc -Wall -pthread threads.c -lpthread
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <assert.h>
pthread_cond_t my_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t my_cond_m = PTHREAD_MUTEX_INITIALIZER;
int * next_work = NULL;
int all_work_done = 0;
void * worker(void * arg)
{
int * my_work = NULL;
while(!all_work_done)
{
pthread_mutex_lock(&my_cond_m);
if(next_work == NULL)
{
// Signal producer to give work
pthread_cond_broadcast(&my_cond);
// Wait for work to arrive
// It is wrapped in a while loop because the condition
// might be triggered by another worker thread intended
// to wake up the producer
while(!next_work && !all_work_done)
pthread_cond_wait(&my_cond, &my_cond_m);
}
// Work has arrived, cache it locally so producer can
// put in next work ASAP
my_work = next_work;
next_work = NULL;
pthread_mutex_unlock(&my_cond_m);
if(my_work)
{
printf("Worker %d consuming work: %d\n", (int)(pthread_self() % 100), *my_work);
free(my_work);
}
}
return NULL;
}
int * create_work()
{
int * ret = (int *)malloc(sizeof(int));
assert(ret);
*ret = rand() % 100;
return ret;
}
void * producer(void * arg)
{
int i;
for(i = 0; i < 10; i++)
{
pthread_mutex_lock(&my_cond_m);
while(next_work != NULL)
{
// There's still work, signal a worker to pick it up
pthread_cond_broadcast(&my_cond);
// Wait for work to be picked up
pthread_cond_wait(&my_cond, &my_cond_m);
}
// No work is available now, let's put work on the queue
next_work = create_work();
printf("Producer: Created work %d\n", *next_work);
pthread_mutex_unlock(&my_cond_m);
}
// Some workers might still be waiting, release them
pthread_cond_broadcast(&my_cond);
all_work_done = 1;
return NULL;
}
int main()
{
pthread_t t1, t2, t3, t4;
pthread_create(&t1, NULL, worker, NULL);
pthread_create(&t2, NULL, worker, NULL);
pthread_create(&t3, NULL, worker, NULL);
pthread_create(&t4, NULL, worker, NULL);
producer(NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
pthread_join(t4, NULL);
return 0;
}

Resources