Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1998 - 2005 Pekka Riikonen
+ Copyright (C) 1998 - 2006 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
const SilcScheduleOps schedule_ops;
-#define SIGNAL_COUNT 32
-
-typedef struct {
- SilcUInt32 signal;
- SilcTaskCallback callback;
- void *context;
- SilcBool call;
-} SilcUnixSignal;
-
/* Internal context. */
typedef struct {
#if defined(HAVE_POLL) && defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
SilcTask wakeup_task;
sigset_t signals;
sigset_t signals_blocked;
- SilcUnixSignal signal_call[SIGNAL_COUNT];
} *SilcUnixScheduler;
+typedef struct {
+ SilcUInt32 sig;
+ SilcTaskCallback callback;
+ void *context;
+ SilcBool call;
+ SilcSchedule schedule;
+} SilcUnixSignal;
+
+#define SIGNAL_COUNT 32
+SilcUnixSignal signal_call[SIGNAL_COUNT];
+
#if defined(HAVE_POLL) && defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
/* Calls normal poll() system call. */
fds = silc_realloc(internal->fds, sizeof(*internal->fds) *
(fds_count + (fds_count / 2)));
- if (!fds)
+ if (silc_unlikely(!fds))
break;
internal->fds = fds;
internal->fds_count = fds_count = fds_count + (fds_count / 2);
void *app_context)
{
SilcUnixScheduler internal;
+ int i;
internal = silc_calloc(1, sizeof(*internal));
if (!internal)
internal->app_context = app_context;
+ for (i = 0; i < SIGNAL_COUNT; i++) {
+ signal_call[i].sig = 0;
+ signal_call[i].call = FALSE;
+ signal_call[i].schedule = schedule;
+ }
+
return (void *)internal;
}
#endif
}
-void silc_schedule_internal_signal_register(SilcSchedule schedule,
- void *context,
- SilcUInt32 signal,
- SilcTaskCallback callback,
- void *callback_context)
+/* Signal handler */
+
+static void silc_schedule_internal_sighandler(int signal)
{
- SilcUnixScheduler internal = (SilcUnixScheduler)context;
int i;
- if (!internal)
- return;
-
- SILC_LOG_DEBUG(("Registering signal %d", signal));
-
- silc_schedule_internal_signals_block(schedule, context);
-
for (i = 0; i < SIGNAL_COUNT; i++) {
- if (!internal->signal_call[i].signal) {
- internal->signal_call[i].signal = signal;
- internal->signal_call[i].callback = callback;
- internal->signal_call[i].context = callback_context;
- internal->signal_call[i].call = FALSE;
+ if (signal_call[i].sig == signal) {
+ signal_call[i].call = TRUE;
+ signal_call[i].schedule->signal_tasks = TRUE;
+ SILC_LOG_DEBUG(("Scheduling signal %d to be called",
+ signal_call[i].sig));
break;
}
}
-
- silc_schedule_internal_signals_unblock(schedule, context);
- sigaddset(&internal->signals, signal);
}
-void silc_schedule_internal_signal_unregister(SilcSchedule schedule,
- void *context,
- SilcUInt32 signal,
- SilcTaskCallback callback,
- void *callback_context)
+void silc_schedule_internal_signal_register(SilcSchedule schedule,
+ void *context,
+ SilcUInt32 sig,
+ SilcTaskCallback callback,
+ void *callback_context)
{
SilcUnixScheduler internal = (SilcUnixScheduler)context;
int i;
if (!internal)
return;
- SILC_LOG_DEBUG(("Unregistering signal %d", signal));
+ SILC_LOG_DEBUG(("Registering signal %d", sig));
silc_schedule_internal_signals_block(schedule, context);
for (i = 0; i < SIGNAL_COUNT; i++) {
- if (internal->signal_call[i].signal == signal &&
- internal->signal_call[i].callback == callback &&
- internal->signal_call[i].context == callback_context) {
- internal->signal_call[i].signal = 0;
- internal->signal_call[i].callback = NULL;
- internal->signal_call[i].context = NULL;
- internal->signal_call[i].call = FALSE;
+ if (!signal_call[i].sig) {
+ signal_call[i].sig = sig;
+ signal_call[i].callback = callback;
+ signal_call[i].context = callback_context;
+ signal_call[i].call = FALSE;
+ signal(sig, silc_schedule_internal_sighandler);
+ break;
}
}
silc_schedule_internal_signals_unblock(schedule, context);
- sigdelset(&internal->signals, signal);
+ sigaddset(&internal->signals, sig);
}
-/* Mark signal to be called later. */
-
-void silc_schedule_internal_signal_call(SilcSchedule schedule,
- void *context, SilcUInt32 signal)
+void silc_schedule_internal_signal_unregister(SilcSchedule schedule,
+ void *context,
+ SilcUInt32 sig)
{
SilcUnixScheduler internal = (SilcUnixScheduler)context;
int i;
if (!internal)
return;
+ SILC_LOG_DEBUG(("Unregistering signal %d", sig));
+
silc_schedule_internal_signals_block(schedule, context);
for (i = 0; i < SIGNAL_COUNT; i++) {
- if (internal->signal_call[i].signal == signal) {
- internal->signal_call[i].call = TRUE;
- SILC_LOG_DEBUG(("Scheduling signal %d to be called",
- internal->signal_call[i].signal));
+ if (signal_call[i].sig == sig) {
+ signal_call[i].sig = 0;
+ signal_call[i].callback = NULL;
+ signal_call[i].context = NULL;
+ signal_call[i].call = FALSE;
+ signal(sig, SIG_DFL);
}
}
silc_schedule_internal_signals_unblock(schedule, context);
+ sigdelset(&internal->signals, sig);
}
/* Call all signals */
silc_schedule_internal_signals_block(schedule, context);
for (i = 0; i < SIGNAL_COUNT; i++) {
- if (internal->signal_call[i].call &&
- internal->signal_call[i].callback) {
+ if (signal_call[i].call &&
+ signal_call[i].callback) {
SILC_LOG_DEBUG(("Calling signal %d callback",
- internal->signal_call[i].signal));
- internal->signal_call[i].callback(schedule, internal->app_context,
- SILC_TASK_INTERRUPT,
- internal->signal_call[i].signal,
- internal->signal_call[i].context);
- internal->signal_call[i].call = FALSE;
+ signal_call[i].sig));
+ signal_call[i].callback(schedule, internal->app_context,
+ SILC_TASK_INTERRUPT,
+ signal_call[i].sig,
+ signal_call[i].context);
+ signal_call[i].call = FALSE;
}
}
silc_schedule_internal_wakeup,
silc_schedule_internal_signal_register,
silc_schedule_internal_signal_unregister,
- silc_schedule_internal_signal_call,
silc_schedule_internal_signals_call,
silc_schedule_internal_signals_block,
silc_schedule_internal_signals_unblock,