2009-01-31 10:33:39 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2016-06-06 11:14:55 -07:00
|
|
|
#include <inttypes.h>
|
|
|
|
#include <stdint.h>
|
2009-01-31 10:33:39 -08:00
|
|
|
#include <stdio.h>
|
2003-09-23 01:09:32 -07:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <unistd.h>
|
2004-04-04 12:53:19 -07:00
|
|
|
#include <assert.h>
|
2018-01-06 00:37:42 -08:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <pthread.h>
|
2009-01-31 10:33:39 -08:00
|
|
|
|
2006-01-06 05:56:47 -08:00
|
|
|
#include "Ecore.h"
|
2009-12-22 13:15:12 -08:00
|
|
|
#include "ecore_private.h"
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2005-01-08 21:17:24 -08:00
|
|
|
/* make mono happy - this is evil though... */
|
|
|
|
#undef SIGPWR
|
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
#define ECORE_SIGNAL_THREAD 1
|
2004-04-04 12:53:19 -07:00
|
|
|
|
2017-12-20 23:34:05 -08:00
|
|
|
static void _ecore_signal_exe_exit_delay(void *data, const Efl_Event *event);
|
2018-01-06 00:37:42 -08:00
|
|
|
static void _ecore_signal_waitpid(Eina_Bool once, siginfo_t info);
|
|
|
|
static void _ecore_signal_generic_free(void *data, void *event);
|
2005-12-30 11:17:21 -08:00
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo);
|
2008-05-03 01:15:16 -07:00
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
#ifdef ECORE_SIGNAL_THREAD
|
|
|
|
static Eina_Thread sig_thread;
|
|
|
|
static Eina_Bool sig_thread_exists = EINA_FALSE;
|
2008-05-03 01:15:16 -07:00
|
|
|
#endif
|
2018-01-06 00:37:42 -08:00
|
|
|
static int sig_pipe[2] = { -1, -1 }; // [0] == read, [1] == write
|
|
|
|
static Eo *sig_pipe_handler = NULL;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
typedef struct _Signal_Data
|
|
|
|
{
|
|
|
|
int sig;
|
|
|
|
siginfo_t info;
|
|
|
|
} Signal_Data;
|
2016-06-06 11:14:55 -07:00
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
static Eina_Bool
|
|
|
|
_ecore_signal_pipe_read(void)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
Signal_Data sdata;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = read(sig_pipe[0], &sdata, sizeof(sdata));
|
|
|
|
if (ret != sizeof(sdata)) return EINA_FALSE;
|
|
|
|
switch (sdata.sig)
|
|
|
|
{
|
|
|
|
case SIGPIPE:
|
|
|
|
break;
|
|
|
|
case SIGALRM:
|
|
|
|
break;
|
|
|
|
case SIGCHLD:
|
|
|
|
_ecore_signal_waitpid(EINA_FALSE, sdata.info);
|
|
|
|
break;
|
|
|
|
case SIGUSR1:
|
|
|
|
case SIGUSR2:
|
|
|
|
{
|
|
|
|
Ecore_Event_Signal_User *e = _ecore_event_signal_user_new();
|
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
if (sdata.sig == SIGUSR1) e->number = 1;
|
|
|
|
else e->number = 2;
|
|
|
|
e->data = sdata.info;
|
|
|
|
ecore_event_add(ECORE_EVENT_SIGNAL_USER, e,
|
|
|
|
_ecore_signal_generic_free, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SIGHUP:
|
|
|
|
{
|
|
|
|
Ecore_Event_Signal_Hup *e = _ecore_event_signal_hup_new();
|
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
e->data = sdata.info;
|
|
|
|
ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e,
|
|
|
|
_ecore_signal_generic_free, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SIGQUIT:
|
|
|
|
case SIGINT:
|
|
|
|
case SIGTERM:
|
|
|
|
{
|
|
|
|
Ecore_Event_Signal_Exit *e = _ecore_event_signal_exit_new();
|
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
if (sdata.sig == SIGQUIT) e->quit = 1;
|
|
|
|
else if (sdata.sig == SIGINT) e->interrupt = 1;
|
|
|
|
else e->terminate = 1;
|
|
|
|
e->data = sdata.info;
|
|
|
|
ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
|
|
|
|
_ecore_signal_generic_free, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2004-04-04 12:53:19 -07:00
|
|
|
#ifdef SIGPWR
|
2018-01-06 00:37:42 -08:00
|
|
|
case SIGPWR:
|
|
|
|
{
|
|
|
|
Ecore_Event_Signal_Power *e = _ecore_event_signal_power_new();
|
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
e->data = sdata.info;
|
|
|
|
ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e,
|
|
|
|
_ecore_signal_generic_free, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2004-04-04 12:53:19 -07:00
|
|
|
#endif
|
2018-01-06 00:37:42 -08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return EINA_TRUE;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
static void
|
|
|
|
_ecore_signal_cb_read(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
while (_ecore_signal_pipe_read());
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
static void
|
|
|
|
_ecore_signal_cb_del(void *data EINA_UNUSED, const Efl_Event *event)
|
2011-09-01 20:29:11 -07:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
if (event->object == sig_pipe_handler) sig_pipe_handler = NULL;
|
2011-09-01 20:29:11 -07:00
|
|
|
}
|
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
EFL_CALLBACKS_ARRAY_DEFINE(_event_watch,
|
|
|
|
{ EFL_LOOP_HANDLER_EVENT_READ, _ecore_signal_cb_read },
|
|
|
|
{ EFL_EVENT_DEL, _ecore_signal_cb_del });
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ecore_signal_callback(int sig, siginfo_t *si, void *foo EINA_UNUSED)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
Signal_Data sdata;
|
|
|
|
|
|
|
|
sdata.sig = sig;
|
|
|
|
sdata.info = *si;
|
|
|
|
if (sdata.sig >= 0) write(sig_pipe[1], &sdata, sizeof(sdata));
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2012-04-13 08:44:02 -07:00
|
|
|
static void
|
2018-01-06 00:37:42 -08:00
|
|
|
_ecore_signal_callback_set(int sig, Signal_Handler func)
|
2012-04-13 08:44:02 -07:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
struct sigaction sa;
|
|
|
|
|
|
|
|
#ifdef ECORE_SIGNAL_THREAD
|
|
|
|
if (eina_thread_self() != sig_thread)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Ecore sig handler NOT called from sigwatcher thread\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
sa.sa_sigaction = func;
|
|
|
|
sa.sa_flags = SA_RESTART | SA_SIGINFO;
|
|
|
|
sigemptyset(&sa.sa_mask);
|
|
|
|
sigaction(sig, &sa, NULL);
|
2012-04-13 08:44:02 -07:00
|
|
|
}
|
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
static void
|
|
|
|
_signalhandler_setup(void)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
sigset_t newset;
|
|
|
|
|
|
|
|
_ecore_signal_callback_set(SIGPIPE, _ecore_signal_callback);
|
|
|
|
_ecore_signal_callback_set(SIGALRM, _ecore_signal_callback);
|
|
|
|
_ecore_signal_callback_set(SIGCHLD, _ecore_signal_callback);
|
|
|
|
_ecore_signal_callback_set(SIGUSR1, _ecore_signal_callback);
|
|
|
|
_ecore_signal_callback_set(SIGUSR2, _ecore_signal_callback);
|
|
|
|
_ecore_signal_callback_set(SIGHUP, _ecore_signal_callback);
|
|
|
|
_ecore_signal_callback_set(SIGQUIT, _ecore_signal_callback);
|
|
|
|
_ecore_signal_callback_set(SIGINT, _ecore_signal_callback);
|
|
|
|
_ecore_signal_callback_set(SIGTERM, _ecore_signal_callback);
|
|
|
|
#ifdef SIGPWR
|
|
|
|
_ecore_signal_callback_set(SIGPWR, _ecore_signal_callback);
|
|
|
|
#endif
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
#ifndef _WIN32
|
2008-05-03 01:15:16 -07:00
|
|
|
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);
|
2018-01-06 00:37:42 -08:00
|
|
|
# ifdef SIGPWR
|
2008-05-03 01:15:16 -07:00
|
|
|
sigaddset(&newset, SIGPWR);
|
2018-01-06 00:37:42 -08:00
|
|
|
# endif
|
|
|
|
pthread_sigmask(SIG_UNBLOCK, &newset, NULL);
|
2008-11-29 03:23:17 -08:00
|
|
|
#endif
|
2018-01-06 00:37:42 -08:00
|
|
|
}
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
static void *
|
|
|
|
_ecore_signal_thread_watcher(void *data EINA_UNUSED, Eina_Thread t)
|
|
|
|
{
|
|
|
|
eina_thread_cancellable_set(EINA_FALSE, NULL);
|
|
|
|
eina_thread_name_set(t, "Esigwatcher");
|
|
|
|
_signalhandler_setup();
|
|
|
|
for (;;) pause();
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
static void
|
|
|
|
_ecore_signal_pipe_init(void)
|
|
|
|
{
|
|
|
|
if (sig_pipe[0] == -1)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
if (pipe(sig_pipe) != 0)
|
2010-09-29 23:09:20 -07:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
sig_pipe[0] = -1;
|
|
|
|
return;
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
2018-01-06 00:37:42 -08:00
|
|
|
eina_file_close_on_exec(sig_pipe[0], EINA_TRUE);
|
|
|
|
eina_file_close_on_exec(sig_pipe[1], EINA_TRUE);
|
|
|
|
fcntl(sig_pipe[0], F_SETFL, O_NONBLOCK);
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2018-01-06 00:37:42 -08:00
|
|
|
#ifdef ECORE_SIGNAL_THREAD
|
|
|
|
if (!sig_thread_exists)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
if (!eina_thread_create(&sig_thread, EINA_THREAD_NORMAL,
|
|
|
|
-1, _ecore_signal_thread_watcher, NULL))
|
2010-09-29 23:09:20 -07:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
close(sig_pipe[0]);
|
|
|
|
close(sig_pipe[1]);
|
|
|
|
sig_pipe[0] = -1;
|
|
|
|
sig_pipe[1] = -1;
|
|
|
|
return;
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
2018-01-06 00:37:42 -08:00
|
|
|
sig_thread_exists = EINA_TRUE;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2018-01-06 00:37:42 -08:00
|
|
|
#else
|
|
|
|
_signalhandler_setup();
|
2004-04-04 12:53:19 -07:00
|
|
|
#endif
|
2018-01-06 00:37:42 -08:00
|
|
|
if (!sig_pipe_handler)
|
|
|
|
sig_pipe_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, ML_OBJ,
|
|
|
|
efl_loop_handler_fd_set(efl_added, sig_pipe[0]),
|
|
|
|
efl_loop_handler_active_set(efl_added, EFL_LOOP_HANDLER_FLAGS_READ),
|
|
|
|
efl_event_callback_array_add(efl_added, _event_watch(), NULL));
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-01-06 00:37:42 -08:00
|
|
|
_ecore_signal_pipe_shutdown(void)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
if (sig_pipe[0] != -1)
|
2011-02-01 02:21:22 -08:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
close(sig_pipe[0]);
|
|
|
|
close(sig_pipe[1]);
|
|
|
|
sig_pipe[0] = -1;
|
|
|
|
sig_pipe[1] = -1;
|
2011-02-01 02:21:22 -08:00
|
|
|
}
|
2018-01-06 00:37:42 -08:00
|
|
|
if (sig_pipe_handler)
|
2011-02-01 02:21:22 -08:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
efl_del(sig_pipe_handler);
|
|
|
|
sig_pipe_handler = NULL;
|
2011-02-01 02:21:22 -08:00
|
|
|
}
|
|
|
|
}
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2011-02-01 02:21:22 -08:00
|
|
|
static void
|
2018-01-06 00:37:42 -08:00
|
|
|
_ecore_signal_cb_fork(void *data EINA_UNUSED)
|
2011-02-01 02:21:22 -08:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
_ecore_signal_pipe_shutdown();
|
|
|
|
#ifdef ECORE_SIGNAL_THREAD
|
|
|
|
sig_thread_exists = EINA_FALSE;
|
|
|
|
#endif
|
|
|
|
_ecore_signal_pipe_init();
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2004-04-04 12:53:19 -07:00
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
void
|
|
|
|
_ecore_signal_init(void)
|
2011-02-01 02:21:22 -08:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
#ifndef _WIN32
|
|
|
|
sigset_t newset;
|
2011-02-01 02:21:22 -08:00
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
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
|
|
|
|
pthread_sigmask(SIG_BLOCK, &newset, NULL);
|
|
|
|
#endif
|
|
|
|
_ecore_signal_pipe_init();
|
|
|
|
ecore_fork_reset_callback_add(_ecore_signal_cb_fork, NULL);
|
2011-02-01 02:21:22 -08:00
|
|
|
}
|
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
void
|
|
|
|
_ecore_signal_shutdown(void)
|
2011-02-01 02:21:22 -08:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
ecore_fork_reset_callback_del(_ecore_signal_cb_fork, NULL);
|
|
|
|
_ecore_signal_pipe_shutdown();
|
|
|
|
// we probably should restore.. but not a good idea
|
|
|
|
// pthread_sigmask(SIG_SETMASK, &sig_oldset, NULL);
|
2011-02-01 02:21:22 -08:00
|
|
|
}
|
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
void
|
|
|
|
_ecore_signal_received_process(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
|
2011-02-01 02:21:22 -08:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
// do nothing - the efl loop handler read event will handle it
|
2011-02-01 02:21:22 -08:00
|
|
|
}
|
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
int
|
|
|
|
_ecore_signal_count_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
|
2011-02-01 02:21:22 -08:00
|
|
|
{
|
2018-01-06 00:37:42 -08:00
|
|
|
// we will always have 0 signals be3cause they will instead be read from
|
|
|
|
// a pipe fd and placed in a queue/list that
|
|
|
|
// _ecore_signal_received_process() will then walk and process/do
|
|
|
|
return 0;
|
2011-02-01 02:21:22 -08:00
|
|
|
}
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2017-12-20 23:34:05 -08:00
|
|
|
static void
|
|
|
|
_ecore_signal_exe_exit_delay(void *data, const Efl_Event *event)
|
2005-12-30 11:17:21 -08:00
|
|
|
{
|
2017-12-20 23:34:05 -08:00
|
|
|
Ecore_Exe_Event_Del *e = data;
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2017-12-20 23:34:05 -08:00
|
|
|
if (!e) return;
|
|
|
|
_ecore_exe_doomsday_clock_set(e->exe, NULL);
|
|
|
|
ecore_event_add(ECORE_EXE_EVENT_DEL, e,
|
|
|
|
_ecore_exe_event_del_free, NULL);
|
|
|
|
efl_del(event->object);
|
2005-12-30 11:17:21 -08:00
|
|
|
}
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2018-01-06 00:37:42 -08:00
|
|
|
static void
|
|
|
|
_ecore_signal_waitpid(Eina_Bool once, siginfo_t info)
|
|
|
|
{
|
|
|
|
pid_t pid;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
|
|
|
|
{
|
|
|
|
Ecore_Exe_Event_Del *e = _ecore_exe_event_del_new();
|
|
|
|
|
|
|
|
//FIXME: If this process is set respawn, respawn with a suitable backoff
|
|
|
|
// period for those that need too much respawning.
|
|
|
|
if (e)
|
|
|
|
{
|
|
|
|
if (WIFEXITED(status))
|
|
|
|
{
|
|
|
|
e->exit_code = WEXITSTATUS(status);
|
|
|
|
e->exited = 1;
|
|
|
|
}
|
|
|
|
else if (WIFSIGNALED(status))
|
|
|
|
{
|
|
|
|
e->exit_signal = WTERMSIG(status);
|
|
|
|
e->signalled = 1;
|
|
|
|
}
|
|
|
|
e->pid = pid;
|
|
|
|
e->exe = _ecore_exe_find(pid);
|
|
|
|
e->data = info; // No need to clone this.
|
|
|
|
if ((e->exe) &&
|
|
|
|
(ecore_exe_flags_get(e->exe) &
|
|
|
|
(ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
|
|
|
|
{
|
|
|
|
/* We want to report the Last Words of the exe, so delay this event.
|
|
|
|
* This is twice as relevant for stderr.
|
|
|
|
* There are three possibilities here -
|
|
|
|
* 1 There are no Last Words.
|
|
|
|
* 2 There are Last Words, they are not ready to be read.
|
|
|
|
* 3 There are Last Words, they are ready to be read.
|
|
|
|
*
|
|
|
|
* For 1 we don't want to delay, for 3 we want to delay.
|
|
|
|
* 2 is the problem. If we check for data now and there
|
|
|
|
* is none, then there is no way to differentiate 1 and 2.
|
|
|
|
* If we don't delay, we may loose data, but if we do delay,
|
|
|
|
* there may not be data and the exit event never gets sent.
|
|
|
|
*
|
|
|
|
* Any way you look at it, there has to be some time passed
|
|
|
|
* before the exit event gets sent. So the strategy here is
|
|
|
|
* to setup a timer event that will send the exit event after
|
|
|
|
* an arbitrary, but brief, time.
|
|
|
|
*
|
|
|
|
* This is probably paranoid, for the less paraniod, we could
|
|
|
|
* check to see for Last Words, and only delay if there are any.
|
|
|
|
* This has it's own set of problems. */
|
|
|
|
efl_del(_ecore_exe_doomsday_clock_get(e->exe));
|
|
|
|
|
|
|
|
Efl_Loop_Timer *doomsday_clock =
|
|
|
|
efl_add(EFL_LOOP_TIMER_CLASS, ML_OBJ,
|
|
|
|
efl_loop_timer_interval_set(efl_added, 0.1),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_TIMER_EVENT_TICK,
|
|
|
|
_ecore_signal_exe_exit_delay, e));
|
|
|
|
_ecore_exe_doomsday_clock_set(e->exe, doomsday_clock);
|
|
|
|
}
|
|
|
|
else ecore_event_add(ECORE_EXE_EVENT_DEL, e,
|
|
|
|
_ecore_exe_event_del_free, NULL);
|
|
|
|
}
|
|
|
|
if (once) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ecore_signal_generic_free(void *data EINA_UNUSED, void *event)
|
|
|
|
{
|
|
|
|
free(event);
|
|
|
|
}
|