I have a multi-threaded program. The main thread uses a getchar to close all the other threads and itself. I have a timer functionality used in one of the child threads. This thread uses SIG34 for timer expiration.
At some point, I receive the SIG34 as below. This is affecting the getchar in my main thread and my program just aborts. Please help me in understanding the same.
Program received signal SIG34, Real-time event 34.
0x00007ffff6ea38cd in read () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0 0x00007ffff6ea38cd in read () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff6e37ff8 in _IO_file_underflow () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007ffff6e3903e in _IO_default_uflow () from /lib/x86_64-linux-gnu/libc.so.6
#3 0x00007ffff6e2fb28 in getchar () from /lib/x86_64-linux-gnu/libc.so.6
#4 0x0000000000401eef in main (argc=1, argv=0x7fffffffe178) at ../../src/SimMain.c:186
Note:
In the child thread, I have assigned SIGRTMIN(translates to SIG34 on my system) for timer signalling and have a handler also. This handler sets a global variable to let me change course post timer expiration. But unsure why getchar is in issue.
Timer Init and usage:
/* Timer macros */
#define CLOCKID CLOCK_REALTIME
#define SIGRT_OFFSET 4 // was 0 before, hence, SIG34, now it is SIG38
#define SIG (SIGRTMIN + SIGRT_OFFSET)
void cc_timer_init()
{
// Install the timer handler...
struct sigevent sev;
long long freq_nanosecs;
struct sigaction disc_action;
/* Establish timer_handler for timer signal */
memset (&disc_action, 0, sizeof (disc_action));
disc_action.sa_flags = SA_SIGINFO; //0 before
disc_action.sa_sigaction = disc_timer_handler;
sigaction(SIG, &disc_action, NULL);
myState = INIT_STATE;
/* Create the timer */
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = &timerid;
timer_create(CLOCKID, &sev, &timerid);
/* Set itimerspec to start the timer */
freq_nanosecs = TMR_TV_NSEC;
v_itimerspec.it_value.tv_sec = TMR_TV_SEC;
v_itimerspec.it_value.tv_nsec = freq_nanosecs % 1000000000;
v_itimerspec.it_interval.tv_sec = 0;
v_itimerspec.it_interval.tv_nsec = 0;
}
static void disc_timer_handler(int sig, siginfo_t *si, void *uc)
{
/* Global variable that I set */
State = MID_1_STATE;
}
/* In another part...*/
.
.
.
case INIT_STATE :
{
v_itimerspec.it_value.tv_sec = TMR_TV_SEC;
timer_settime(timerid, 0, &v_itimerspec, NULL);
ret_val = SUCCESS;
}
break;
.
.
.
From the ubuntu pthreads information sheet (LinuxThreads)):
In addition to the main (initial) thread, and the threads that the
program creates using pthread_create(3), the implementation creates
a "manager" thread. This thread handles thread creation and
termination. (Problems can result if this thread is inadvertently
killed.)
- Signals are used internally by the implementation. On Linux 2.2 and
later, the first three real-time signals are used.
Other implementations use the first two RT signals. Set SIGRTMIN above these two/three signals that used by threading management. See what your pthreads(7) man page says about SIGRTMIN. And adjust accordingly.
Related
I'm learning THE LINUX PROGRAMING INTERFACE this book and get confused here.
I invoke the pthread_attr_getdetachstate() and find that thread created by mq_notify() it's JOINABLE, but how to pthread_join() this zoomble(after it terminated) thread?
I saw the man page, but he doesn't use join.
I just looked at the glibc source code for mq_notify.
mq_notify starts a single control thread with PTHREAD_CREATE_DETACHED. Therefore, it is not joinable.
The pthread_t value that gets set by the call from mq_notify to pthread_create is not available to you. So, whatever value you're using in your pthread_attr_getdetachstate call has no relationship to the mq_notify call.
This control thread created by mq_notify may create other threads. But, they also run detached [using pthread_detach(pthread_self())].
UPDATE:
I wonder whether the OP is talking about using SIGEV_THREAD to receive message notifications. It makes some sense that they would want to know about how to manage the thread in which their specified function is called. – John Bollinger
In the glibc wrapper function mq_notify ...
The first time mq_notify is called, it creates a netlink socket for communication and a single control thread.
In the sigevent struct [from caller], if sigev_notify is SIGEV_THREAD, the struct can have a [non-null] pthread_attr_t * value in sigev_notify_attributes. These attributes are copied and passed off to the actual mq_notify syscall via an internal struct
This is because although the syscall could create a thread [via an internal clone call], it could not do this from a signal handler and all the things that pthread_* functions do to (e.g.) set up pthread_t could not be done by the kernel.
So, after that, the [internal] struct is [ultimately] sent to the control thread [from the kernel] via a message on the netlink socket. The thread function for the control thread is [in the code below]: helper_function
The control thread will set the attributes from that message/struct into the pthread_create call it issues to start a [per-message] notification thread.
But ... The start routine specified in the pthread_create is not caller's notification/thread function. It is another wrapper function (e.g. notification_function) that calls pthread_detach as I mentioned above. It then calls user's start function.
I could be misreading the code, but, AFAICT, by the time the user's callback function has been invoked, it is in a separate thread that has already been detached.
So, again, the thread is not joinable. Whether the pthread_detach call updates the attributes of the per-message thread so that the caller can do: pthread_attribute_getdetachstate(pthread_self(),...) and get this is a bit of a moot point. We know it's detached.
So, user/caller's thread function can't pthread_join itself. And, caller's original thread can no longer manage the notification thread [because, again, it's detached], there really isn't anything to do [or anything that can be done].
Here's an excerpt from sysdeps/unix/sysv/linux/mq_notify.c:
/* The function used for the notification. */
static void *
notification_function(void *arg)
{
/* Copy the function and parameter so that the parent thread can go on with its life. */
volatile union notify_data *data = (volatile union notify_data *) arg;
void (*fct) (union sigval) = data->fct;
union sigval param = data->param;
/* Let the parent go. */
(void) __pthread_barrier_wait(¬ify_barrier);
/* Make the thread detached. */
(void) pthread_detach(pthread_self());
/* The parent thread has all signals blocked. This is probably a bit surprising for this thread. So we unblock all of them. */
(void) change_sigmask(SIG_UNBLOCK, NULL);
/* Now run the user code. */
fct(param);
/* And we are done. */
return NULL;
}
/* Helper thread. */
static void *
helper_thread(void *arg)
{
while (1) {
union notify_data data;
ssize_t n = __recv(netlink_socket, &data, sizeof(data),
MSG_NOSIGNAL | MSG_WAITALL);
if (n < NOTIFY_COOKIE_LEN)
continue;
if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_WOKENUP) {
/* Just create the thread as instructed. There is no way to report a problem with creating a thread. */
pthread_t th;
if (__builtin_expect(pthread_create(&th, data.attr, notification_function, &data)
== 0, 0))
/* Since we passed a pointer to DATA to the new thread we have to wait until it is done with it. */
(void) __pthread_barrier_wait(¬ify_barrier);
}
else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED)
/* The only state we keep is the copy of the thread attributes. */
free(data.attr);
}
return NULL;
}
static void
reset_once(void)
{
once = PTHREAD_ONCE_INIT;
}
static void
init_mq_netlink(void)
{
/* This code might be called a second time after fork(). The file descriptor is inherited from the parent. */
if (netlink_socket == -1) {
/* Just a normal netlink socket, not bound. */
netlink_socket = __socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, 0);
/* No need to do more if we have no socket. */
if (netlink_socket == -1)
return;
}
int err = 1;
/* Initialize the barrier. */
if (__builtin_expect(__pthread_barrier_init(¬ify_barrier, NULL, 2) == 0, 0)) {
/* Create the helper thread. */
pthread_attr_t attr;
(void) pthread_attr_init(&attr);
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
/* We do not need much stack space, the bare minimum will be enough. */
(void) pthread_attr_setstacksize(&attr, __pthread_get_minstack(&attr));
/* Temporarily block all signals so that the newly created thread inherits the mask. */
sigset_t oss;
int have_no_oss = change_sigmask(SIG_BLOCK, &oss);
pthread_t th;
err = pthread_create(&th, &attr, helper_thread, NULL);
/* Reset the signal mask. */
if (!have_no_oss)
pthread_sigmask(SIG_SETMASK, &oss, NULL);
(void) pthread_attr_destroy(&attr);
if (err == 0) {
static int added_atfork;
if (added_atfork == 0 && pthread_atfork(NULL, NULL, reset_once) != 0) {
/* The child thread will call recv() which is a cancellation point. */
(void) pthread_cancel(th);
err = 1;
}
else
added_atfork = 1;
}
}
if (err != 0) {
__close_nocancel_nostatus(netlink_socket);
netlink_socket = -1;
}
}
/* Register notification upon message arrival to an empty message queue
MQDES. */
int
mq_notify(mqd_t mqdes, const struct sigevent *notification)
{
/* Make sure the type is correctly defined. */
assert(sizeof(union notify_data) == NOTIFY_COOKIE_LEN);
/* Special treatment needed for SIGEV_THREAD. */
if (notification == NULL || notification->sigev_notify != SIGEV_THREAD)
return INLINE_SYSCALL(mq_notify, 2, mqdes, notification);
/* The kernel cannot directly start threads. This will have to be done at userlevel. Since we cannot start threads from signal handlers we have to create a dedicated thread which waits for notifications for arriving messages and creates threads in response. */
/* Initialize only once. */
pthread_once(&once, init_mq_netlink);
/* If we cannot create the netlink socket we cannot provide SIGEV_THREAD support. */
if (__glibc_unlikely(netlink_socket == -1)) {
__set_errno(ENOSYS);
return -1;
}
/* Create the cookie. It will hold almost all the state. */
union notify_data data;
memset(&data, '\0', sizeof(data));
data.fct = notification->sigev_notify_function;
data.param = notification->sigev_value;
if (notification->sigev_notify_attributes != NULL) {
/* The thread attribute has to be allocated separately. */
data.attr = (pthread_attr_t *) malloc(sizeof(pthread_attr_t));
if (data.attr == NULL)
return -1;
memcpy(data.attr, notification->sigev_notify_attributes, sizeof(pthread_attr_t));
}
/* Construct the new request. */
struct sigevent se;
se.sigev_notify = SIGEV_THREAD;
se.sigev_signo = netlink_socket;
se.sigev_value.sival_ptr = &data;
/* Tell the kernel. */
int retval = INLINE_SYSCALL(mq_notify, 2, mqdes, &se);
/* If it failed, free the allocated memory. */
if (__glibc_unlikely(retval != 0))
free(data.attr);
return retval;
}
Setting a signal handler as SIG_IGN ignores the signal while running the program normally but not while running it through gdb.
I'm creating a timer using timer_create and timer_settime functions. I don't want to use a signal handler (i.e a function) to handle the signals generated by this timer. I decided to use sigwait and wait for SIGALRM. I set the handler for SIGALRM as SIG_IGN and used sigwait.
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#define TRUE 1
#define ISTRUE(x) (x != 0)
#define bool int
int main() {
struct itimerspec timer_spec;
struct sigevent sig_event;
timer_t timer_id;
sigset_t sig_set;
timer_spec.it_interval.tv_sec = 1;
timer_spec.it_interval.tv_nsec = 0;
timer_spec.it_value.tv_sec = 1;
timer_spec.it_value.tv_nsec = 0;
sig_event.sigev_signo = SIGALRM;
sig_event.sigev_notify = SIGEV_SIGNAL;
signal(SIGINT, SIG_IGN);
signal(SIGALRM, SIG_IGN);
/* Create the timer */
timer_create(CLOCK_REALTIME, &sig_event, &timer_id);
timer_settime(timer_id, 0, &timer_spec, NULL);
sigemptyset(&sig_set);
sigaddset(&sig_set, SIGALRM);
int signal = 0;
bool running = TRUE;
while (ISTRUE(running)) {
sigwait(&sig_set, &signal);
switch(signal){
case SIGINT:
printf("Interrupt received.. exiting\n");
running = 0;
break;
case SIGALRM:
printf("Ticked\n");
break;
}
printf("Sleeping\n");
}
return 0;
}
While debugging the application in my IDE (CLion) as well as using gdb from the shell, the program functioned as expected. SIGALRM was not being ignored, which led me to believe that what I was doing was right. However, running the application normally, sigwait never returns.
I later realized that this was because the signal was being ignored and I needed to block the signal (using sigprocmask or similar) and set it to a pending state.
Why does, while debugging, the signal get passed through? Is this supposed to happen? What am I missing?
You should look into the handle gdb command:
(gdb) handle SIGALRM
Signal Stop Print Pass to program Description
SIGALRM No No Yes Alarm clock
(gdb) handle SIGALRM ignore
Signal Stop Print Pass to program Description
SIGALRM No No No Alarm clock
(gdb) help handle
... read it ;-) ...
As mentioned in the manpage of ptrace(2) (which gdb is using):
While being traced, the tracee will stop each time a signal is delivered, even if the signal is being ignored.
I want to call timer_handler function at every 2 seconds regardless of execution time of timer_handler function here is my code
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
void timer_handler (int signum)
{
static int count = 0;
sleep(1);
printf ("timer expired %d times %d signum \n", ++count, signum);
}
int main ()
{
struct sigaction sa;
struct itimerval timer;
/* timer_handler as the signal handler for SIGVTALRM. */
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGVTALRM, &sa, NULL);
/* Configure the timer to expire after 2000 msec... */
timer.it_value.tv_sec = 2;
timer.it_value.tv_usec = 0;
/* ... and every 2000 msec after that. */
timer.it_interval.tv_sec = 2;
timer.it_interval.tv_usec = 0;
/* Start a virtual timer. It counts down whenever this process is
executing. */
setitimer (ITIMER_VIRTUAL, &timer, NULL);
/* Do busy work. */
while (1);
}
As per above code it should print timer expired 1 times 26 signum at every two second but its prints on every 3 seconds which includes sleep time so i want to call that function on every 2 seconds.
I don't know where i am doing wrong
If any other library is able to do this please let me know
Thank you
Why not use wall-clock time?
To do so
install the signal handler for SIGALRM instead of SIGVTALRM and
specify ITIMER_REAL instead of ITIMER_VIRTUAL.
Unrelated but important: Signal handlers may only call async-signal-safe functions. printf() is not one of those. For a list of the latter click here and scroll down.
the call, in the signal handler: sleep(1) is adding an extra second to the processing of the signal. This extra second is not part of the execution time of the process.
remove from the signal handler:
sleep(1);
regarding:
setitimer (ITIMER_VIRTUAL, &timer, NULL);
since you want to see the signal handler executed every 2 seconds, the proper timer to use is: ITIMER_REAL not ITIMER_VIRTUAL. This will result in the 'clock on the wall' time being measured rather than the 'process run' time being measured.
Strongly suggest having the signal handler ONLY set a flag. Then the 'do nothing' loop in the main function be checking that flag, reset the flag, then call printf()` To properly accomplish this, with out an 'race' conditions, use a mutex/ Both the main and the signal handler would lock the mutex, modify the flag, then unlock the mutex.
I've got the following function that gets called from a pthread_create. This function does some work, sets a timer, does some other work and then waits for the timer to expire before doing the loop again. However, on the first run of the timer, after it expires the program quits and I'm not totally sure why. It should never leave the infinite while loop. The main thread accesses nothing from this thread and vice versa (for now).
My guess is I might not have something setup correctly with the thread, or the timer is not calling the handler function correctly. Perhaps changing the IDLE global variable from the thread causes a problem.
I would like to call the handler without signals, hence the use of SIGEV_THREAD_ID. I'm using the SIGUSRx signals in the main thread anyway. Any thoughts about what I've started here what could be wrong?
#ifndef sigev_notify_thread_id
#define sigev_notify_thread_id _sigev_un._tid
#endif
volatile sig_atomic_t IDLE = 0;
timer_t timer_id;
struct sigevent sev;
void handler() {
printf("Timer expired.\n");
IDLE = 0;
}
void *thread_worker() {
struct itimerspec ts;
/* setup the handler for timer event */
memset (&sev, 0, sizeof(struct sigevent));
sev.sigev_notify = SIGEV_THREAD_ID;
sev.sigev_value.sival_ptr = NULL;
sev.sigev_notify_function = handler;
sev.sigev_notify_attributes = NULL;
sev.sigev_signo = SIGRTMIN + 1;
sev.sigev_notify_thread_id = syscall(SYS_gettid);
/* setup "idle" timer */
ts.it_value.tv_sec = 55;
ts.it_value.tv_nsec = 0;
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
if (timer_create(0, &sev, &timer_id) == -1) {
printf("timer_create failed: %d: %s\n", errno, strerror(errno));
exit(3);
}
while (1) {
// do work here before timer gets started that takes 5 seconds
while (IDLE); /* wait here until timer_id expires */
/* setup timer */
if (timer_settime(timer_id, 0, &ts, NULL) == -1) {
printf("timer_settime failed: %d\n", errno);
exit(3);
}
IDLE = 1;
// do work here while timer is running but that does not take 10 seconds
}
}
As far as I can tell, you haven't installed a signal handler for SIGUSR1, so by the default action it kills the process when it's acted upon.
In any case, the whole thing strikes me as extraordinarily bad design:
The while loop will give you 100% cpu load while waiting for the timer to expire.
This is not the way you use SIGEV_THREAD_ID, and in fact SIGEV_THREAD_ID isn't really setup to be usable by applications. Rather it's for the libc to use internally for implementing SIGEV_THREAD.
You really don't want to be using signals. They're messy.
If you have threads, why aren't you just calling clock_nanosleep in a loop? Timers are mainly useful when you can't do this, e.g. when you can't use threads.
The main function is based on libevent, but there is a long run task in the function. So start N treads to run the tasks. Is is this idea OK? And how to use libevent and pthread together in C?
Bumping an old question, may have already been solved. But posting the answer just in case someone else needs it.
Yes, it is okay to do threading in this case. I recently used libevent in pthreads, and it seems to be working just fine. Here's the code :
#include <stdint.h>
#include <pthread.h>
#include <event.h>
void * thread_func (void *);
int main(void)
{
int32_t tid = 0, ret = -1;
struct event_base *evbase;
struct event *timer;
int32_t *t_ret = &ret;
struct timeval tv;
// 1. initialize libevent for pthreads
evthread_use_pthreads();
ret = pthread_create(&tid, NULL, thread_func, NULL);
// check ret for error
// 2. allocate event base
evbase = event_base_new();
// 3. allocate event object
timer = event_new(evbase, -1, EV_PERSIST, callback_func, NULL);
// 4. add event
tv.tv_sec = 0;
tv.tv_usec = 1000;
evtimer_add(timer, &tv);
// 5. start the event loop
event_base_dispatch(evbase); // event loop
// join pthread...
// 6. free resources
event_free(timer);
event_base_free(evbase);
return 0;
}
void * thread_func(void *arg)
{
struct event *ev;
struct event_base *base;
base = event_base_new();
ev = event_new(base, -1, EV_PERSIST, thread_callback, NULL);
event_add(ev, NULL); // wait forever
event_base_dispatch(base); // start event loop
event_free(ev);
event_base_free(base);
pthread_exit(0);
}
As you can see, in my case, the event for the main thread is timer. The base logic followed is as below :
call evthread_use_pthreads() to initialize libevent for pthreads on Linux (my case). For windows evthread_use_window_threads(). Check out the documentation given in event.h itself.
Allocate an event_base structure on global heap as instructed in documentation. Make sure to check return value for errors.
Same as above, but allocate event structure itself. In my case, I am not waiting on any file descriptor, so -1 is passed as argument. Also, I want my event to persist, hence EV_PERSIST . The code for callback functions is omitted.
Schedule the event for execution
Start the event loop
free the resources when done.
Libevent version used in my case is libevent2 5.1.9 , and you will also need libevent_pthreads.so library for linking.
cheers.
That would work.
In the I/O callback function delegates time consuming job to another thread of a thread pool. The exact mechanics depend on the interface of the worker thread or the thread pool.
To communicate the result back from the worker thread to the I/O thread use a pipe. The worker thread writes the pointer to the result object to the pipe and the I/O thread
wakes up and read the pointer from the pipe.
There is a multithreaded libevent example in this blog post:
http://www.roncemer.com/multi-threaded-libevent-server-example
His solution is, to quote:
The solution is to create one libevent event queue (AKA event_base) per active connection, each with its own event pump thread. This project does exactly that, giving you everything you need to write high-performance, multi-threaded, libevent-based socket servers.
NOTE This is for libev not libevent but the idea may apply.
Here I present an example for the community. Please comment and let me know if there are any noticable bugs. This example could include a signal handler for thread termination and graceful exit in the future.
//This program is demo for using pthreads with libev.
//Try using Timeout values as large as 1.0 and as small as 0.000001
//and notice the difference in the output
//(c) 2009 debuguo
//(c) 2013 enthusiasticgeek for stack overflow
//Free to distribute and improve the code. Leave credits intact
//compile using: gcc -g test.c -o test -lpthread -lev
#include <ev.h>
#include <stdio.h> // for puts
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t lock;
double timeout = 0.00001;
ev_timer timeout_watcher;
int timeout_count = 0;
ev_async async_watcher;
int async_count = 0;
struct ev_loop* loop2;
void* loop2thread(void* args)
{
// now wait for events to arrive on the inner loop
ev_loop(loop2, 0);
return NULL;
}
static void async_cb (EV_P_ ev_async *w, int revents)
{
//puts ("async ready");
pthread_mutex_lock(&lock); //Don't forget locking
++async_count;
printf("async = %d, timeout = %d \n", async_count, timeout_count);
pthread_mutex_unlock(&lock); //Don't forget unlocking
}
static void timeout_cb (EV_P_ ev_timer *w, int revents) // Timer callback function
{
//puts ("timeout");
if(ev_async_pending(&async_watcher)==false){ //the event has not yet been processed (or even noted) by the event loop? (i.e. Is it serviced? If yes then proceed to)
ev_async_send(loop2, &async_watcher); //Sends/signals/activates the given ev_async watcher, that is, feeds an EV_ASYNC event on the watcher into the event loop.
}
pthread_mutex_lock(&lock); //Don't forget locking
++timeout_count;
pthread_mutex_unlock(&lock); //Don't forget unlocking
w->repeat = timeout;
ev_timer_again(loop, &timeout_watcher); //Start the timer again.
}
int main (int argc, char** argv)
{
if (argc < 2) {
puts("Timeout value missing.\n./demo <timeout>");
return -1;
}
timeout = atof(argv[1]);
struct ev_loop *loop = EV_DEFAULT; //or ev_default_loop (0);
//Initialize pthread
pthread_mutex_init(&lock, NULL);
pthread_t thread;
// This loop sits in the pthread
loop2 = ev_loop_new(0);
//This block is specifically used pre-empting thread (i.e. temporary interruption and suspension of a task, without asking for its cooperation, with the intention to resume that task later.)
//This takes into account thread safety
ev_async_init(&async_watcher, async_cb);
ev_async_start(loop2, &async_watcher);
pthread_create(&thread, NULL, loop2thread, NULL);
ev_timer_init (&timeout_watcher, timeout_cb, timeout, 0.); // Non repeating timer. The timer starts repeating in the timeout callback function
ev_timer_start (loop, &timeout_watcher);
// now wait for events to arrive on the main loop
ev_loop(loop, 0);
//Wait on threads for execution
pthread_join(thread, NULL);
pthread_mutex_destroy(&lock);
return 0;
}