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.
/* function to be executed by the new thread */
void* do_loop(void* data)
{
int i; /* counter, to print numbers */
int j; /* counter, for delay */
int me = *((int*)data); /* thread identifying number */
kill(getpid(), mySig);
int main(int argc, char* argv[])
{
int thr_id; /* thread ID for the newly created thread */
pthread_t p_thread; /* thread's structure */
int a = 1; /* thread 1 identifying number */
int b = 2; /* thread 2 identifying number */
signal(mySig, mySigHandle);
/* create a new thread that will execute 'do_loop()' */
thr_id = pthread_create(&p_thread, NULL, do_loop, (void*)&a);
/* run 'do_loop()' in the main thread as well */
do_loop((void*)&b);
return 0;
}
Inside mySigHandle function I want to know which thread has raised the signal(main
thread or created thread)
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#define mySig 41
void mySigHandle(int i)
{
printf("Hi");
}
/* function to be executed by the new thread */
void* do_loop(void* data)
{
int i; /* counter, to print numbers */
int j; /* counter, for delay */
int me = *((int*)data); /* thread identifying number */
kill(getpid(), mySig);
for (i=0; i<10; i++) {
for (j=0; j<500000; j++) /* delay loop */
;
printf("'%d' - Got '%d'\n", me, i);
}
/* terminate the thread */
pthread_exit(NULL);
}
int main(int argc, char* argv[])
{
int thr_id; /* thread ID for the newly created thread */
pthread_t p_thread; /* thread's structure */
int a = 1; /* thread 1 identifying number */
int b = 2; /* thread 2 identifying number */
signal(mySig, mySigHandle);
/* create a new thread that will execute 'do_loop()' */
thr_id = pthread_create(&p_thread, NULL, do_loop, (void*)&a);
/* run 'do_loop()' in the main thread as well */
do_loop((void*)&b);
return 0;
}
Inside do_loop function I want to know which thread has raised the signal(main
thread or created thread)
I suppose you mean you want to know that in the mySigHandle function.
I'm not an expert on signals, but it's my educated guess that you need to use things like message queues/mailboxes if you want to communicate more information than just the signal itself.
Had some fun with the code you posted. I used semaphores to
lock/unlock a common resource between threads. You may also
want to see pthread_mutex_init(). I have to admit my code does
have some problems (even numbered threads just won't start!).
Hope this helps.
Code:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <errno.h>
#define mySig 41
#define THREADS 25
struct thread_data
{
int thread_id;
int sem_id;
};
int sem_id;
int gloThreadId = 0;
/*
* gotta put this in per semctl man page
*/
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* union semun is defined by including <sys/sem.h> */
#else
/* according to X/OPEN we have to define it ourselves */
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
unsigned short int *array; /* array for GETALL, SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
};
#endif
void mySigHandle(int i)
{
printf("Thread %d: Hi\n", gloThreadId);
}
void request_sem(int semid, int i)
{
struct sembuf sbuf;
sbuf.sem_num= 0;
sbuf.sem_op = -1;
sbuf.sem_flg = SEM_UNDO;
printf("Thread %d requesting lock\n", i);
semop(semid, &sbuf, 1);
}
void release_sem(int semid, int i)
{
struct sembuf sbuf;
sbuf.sem_num = 0;
sbuf.sem_op = 1;
sbuf.sem_flg = SEM_UNDO;
printf("Thread %d releasing lock\n", i);
semop(semid, &sbuf, 1);
}
/* function to be executed by the new thread */
void* do_loop(void* data)
{
int i; /* counter, to print numbers */
int j; /* counter, for delay */
int me = (*(struct thread_data*)data).thread_id; /* thread identifying number */
int semid = (*(struct thread_data*)data).sem_id; /* semaphore id number */
printf("Thread %d starting up!\n", me);
request_sem(semid, me);
gloThreadId = me;
kill(getpid(), mySig);
release_sem(semid, me);
for (i=0; i<10; i++)
{
sleep(1);
//printf("Thread '%d' = '%d'\n", me, i);
}
/* terminate the thread */
pthread_exit(NULL);
}
struct pthread_stuff
{
int thread_id;
pthread_t p_thread;
} pthread_array[50];
int main(int argc, char* argv[])
{
union semun sun;
struct thread_data tdata;
int i;
/* create a semaphore */
tdata.sem_id = semget(IPC_PRIVATE, 1, SHM_R | SHM_W);
if(tdata.sem_id != 1)
{
/* set resource to 1 */
sun.val = 1;
if( semctl(tdata.sem_id, 0, SETVAL, sun) == -1 )
{
printf("bailing out: semctl() failed [%s]\n", strerror(errno));
exit(2);
}
}
else
{
printf("bailing out: semget() problems [%s]\n", strerror(errno));
}
signal(mySig, mySigHandle);
for( i = 1; i <= THREADS; i++ )
{
printf("i = %d\n", i);
/* fixup tdata for thread 1 */
tdata.thread_id = i;
/* create a new thread that will execute 'do_loop()' */
pthread_array[i].thread_id = pthread_create(&pthread_array[i].p_thread, NULL, do_loop, (void*)&tdata);
if( pthread_array[i].thread_id != 0 )
{
printf("Thread not created! %d\n", i);
}
}
/* fixup tdata for thread 2; could be done in a for loop for multiple threads*/
tdata.thread_id = i++;
/* run 'do_loop()' in the main thread as well */
do_loop((void*)&tdata);
/* clean up after ourselves */
semctl(tdata.sem_id, 0, IPC_RMID, 0);
return 0;
}
Thanks for your reply, but that is not the case that I want
In the previous case you are throwing that signal then you can have that luxury to get a lock, change the global variable to the current thread id, throw signal and unlock it, but think about signals thrown by system such as SIGSEGV then how will you get the thread-id inside that signal handler.
Getting on a tangent here:
Would it be practical or possible to extend the functions in signal.h to
accept variable length arguments as a last parameter? I would assume
that this would make the functions backwards compatible with older
programs and would allow you to pass data.
typedef void (*__sighandler_t) (int, ... );
extern int kill( __pid_t __pid, int __sig, ...) __THROW;
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.