efl - threads and signals - make efl work on "insane" os's with signals

so. on linux signals are delivered to the main process thread/loop.
thats' where signal handlers are set up and always run. this is sane.
it's predicatble. but of course this is not the same in bsd land.
there "just send the signal to any old thread and call the signal
handler there" seems to tbe the order of the day. this explains why
wer are losing sigchld signals in edje_cc - it's heavily threaded and
bsd is just randombly picking a thread to call it on.

this fixes that. in theory. i hope. i can't test, but putting it in to
share

@fix
This commit is contained in:
Carsten Haitzler 2016-07-04 23:47:25 +09:00
parent f72c475867
commit aeeda1f77d
5 changed files with 70 additions and 7 deletions

7
README
View File

@ -32,12 +32,7 @@ PLATFORMS
EFL is primarily developerd on Linux (GNU/Linux) and should work on
most distributions as long as dependencies are provided. It has been
compiled and run also on Windows (using MINGW32 - please see
http://www.winbuilds.org ), Mac OS X, FreeBSD and NetBSD. Due to
serious bugs in OpenBSD, EFL cannot be compiled or used there. Please
see:
https://www.mail-archive.com/search?l=misc@openbsd.org&q=subject:%22SIGCHLD+and+libpthread.so%22&o=newest&f=1
http://www.winbuilds.org ), Mac OS X, FreeBSD and NetBSD.
COMPONENTS
----------

View File

@ -507,6 +507,7 @@ cserve2_slave_thread_run(Slave_Thread_Cb thread_cb, void *thread_data, Slave_Rea
pthread_t tid;
int child[2], parent[2];
int flags;
sigset_t oldset, newset;
s = calloc(1, sizeof(Slave_Thread));
if (!s)
@ -550,8 +551,23 @@ cserve2_slave_thread_run(Slave_Thread_Cb thread_cb, void *thread_data, Slave_Rea
sd->cb = thread_cb;
sd->cb_data = thread_data;
sigemptyset(&newset);
sigaddset(&newset, SIGPIPE);
sigaddset(&newset, SIGALRM);
sigaddset(&newset, SIGCHLD);
sigaddset(&newset, SIGUSR1);
sigaddset(&newset, SIGUSR2);
sigaddset(&newset, SIGHUP);
sigaddset(&newset, SIGQUIT);
sigaddset(&newset, SIGINT);
sigaddset(&newset, SIGTERM);
#ifdef SIGPWR
sigaddset(&newset, SIGPWR);
#endif
sigprocmask(SIG_BLOCK, &newset, &oldset);
if (pthread_create(&tid, &slave_thread_attr, _slave_thread_cb, sd))
{
sigprocmask(SIG_SETMASK, &oldset, NULL);
ERR("Could not start slave thread.");
free(s);
free(sd);
@ -561,6 +577,7 @@ cserve2_slave_thread_run(Slave_Thread_Cb thread_cb, void *thread_data, Slave_Rea
close(parent[1]);
return NULL;
}
sigprocmask(SIG_SETMASK, &oldset, NULL);
s->tid = tid;
s->tdata = sd;

View File

@ -20,6 +20,7 @@
#include "eina_types.h"
#include "eina_evlog.h"
#include "eina_util.h"
#include <signal.h>
#ifdef EINA_HAVE_DEBUG
@ -355,11 +356,27 @@ void
_eina_debug_monitor_thread_start(void)
{
int err;
sigset_t oldset, newset;
// if it's already running - we're good.
if (_monitor_thread_runs) return;
// create debug monitor thread
sigemptyset(&newset);
sigaddset(&newset, SIGPIPE);
sigaddset(&newset, SIGALRM);
sigaddset(&newset, SIGCHLD);
sigaddset(&newset, SIGUSR1);
sigaddset(&newset, SIGUSR2);
sigaddset(&newset, SIGHUP);
sigaddset(&newset, SIGQUIT);
sigaddset(&newset, SIGINT);
sigaddset(&newset, SIGTERM);
#ifdef SIGPWR
sigaddset(&newset, SIGPWR);
#endif
sigprocmask(SIG_BLOCK, &newset, &oldset);
err = pthread_create(&_monitor_thread, NULL, _eina_debug_monitor, NULL);
sigprocmask(SIG_SETMASK, &oldset, NULL);
if (err != 0)
{
fprintf(stderr, "EINA DEBUG ERROR: Can't create debug thread!\n");

View File

@ -34,6 +34,7 @@
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#if defined(EINA_HAVE_PTHREAD_AFFINITY) || defined(EINA_HAVE_PTHREAD_SETNAME)
#ifndef __linux__
@ -57,6 +58,7 @@ _eina_thread_create(Eina_Thread *t, int affinity, void *(*func)(void *data), voi
{
int err;
pthread_attr_t attr;
sigset_t oldset, newset;
pthread_attr_init(&attr);
if (affinity >= 0)
@ -74,7 +76,22 @@ _eina_thread_create(Eina_Thread *t, int affinity, void *(*func)(void *data), voi
}
/* setup initial locks */
sigemptyset(&newset);
sigaddset(&newset, SIGPIPE);
sigaddset(&newset, SIGALRM);
sigaddset(&newset, SIGCHLD);
sigaddset(&newset, SIGUSR1);
sigaddset(&newset, SIGUSR2);
sigaddset(&newset, SIGHUP);
sigaddset(&newset, SIGQUIT);
sigaddset(&newset, SIGINT);
sigaddset(&newset, SIGTERM);
#ifdef SIGPWR
sigaddset(&newset, SIGPWR);
#endif
sigprocmask(SIG_BLOCK, &newset, &oldset);
err = pthread_create((pthread_t *)t, &attr, func, data);
sigprocmask(SIG_SETMASK, &oldset, NULL);
pthread_attr_destroy(&attr);
if (err == 0) return EINA_TRUE;

View File

@ -5,6 +5,7 @@
#include <Eina.h>
#include <Evas.h>
#include <Ecore.h>
#include <signal.h>
#include "emotion_modules.h"
#include "emotion_xine.h"
@ -322,6 +323,7 @@ em_add(const Emotion_Engine *api EINA_UNUSED,
{
Emotion_Xine_Video *ev;
int fds[2];
sigset_t oldset, newset;
ev = calloc(1, sizeof(Emotion_Xine_Video));
EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);
@ -366,9 +368,24 @@ em_add(const Emotion_Engine *api EINA_UNUSED,
pthread_cond_init(&(ev->get_pos_len_cond), NULL);
pthread_mutex_init(&(ev->get_pos_len_mutex), NULL);
sigemptyset(&newset);
sigaddset(&newset, SIGPIPE);
sigaddset(&newset, SIGALRM);
sigaddset(&newset, SIGCHLD);
sigaddset(&newset, SIGUSR1);
sigaddset(&newset, SIGUSR2);
sigaddset(&newset, SIGHUP);
sigaddset(&newset, SIGQUIT);
sigaddset(&newset, SIGINT);
sigaddset(&newset, SIGTERM);
#ifdef SIGPWR
sigaddset(&newset, SIGPWR);
#endif
sigprocmask(SIG_BLOCK, &newset, &oldset);
pthread_create(&ev->get_pos_len_th, NULL, _em_get_pos_len_th, ev);
pthread_create(&ev->slave_th, NULL, _em_slave, ev);
sigprocmask(SIG_SETMASK, &oldset, NULL);
pthread_detach(ev->slave_th);
_em_slave_event(ev, 1, NULL);