diff --git a/oop.h b/oop.h index d5d82ac534474e976d535c3a5403a619acd76536..2ab7c67940c157f71b18e3ccfe63fb77bcfabd07 100644 --- a/oop.h +++ b/oop.h @@ -85,6 +85,12 @@ void oop_sys_delete(oop_source_sys *); /* Get the event registration interface for a system event source. */ oop_source *oop_sys_source(oop_source_sys *); +/* Set SA_RESTART in the sa_flags field of struct sigaction, so that + syscalls are restarted. This is a global setting, and the function + must be called before the first signal handler is registered. + There is no way to undo the setting. */ +void oop_sys_use_sa_restart(void); + /* ------------------------------------------------------------------------- */ /* Helper for select-style asynchronous interfaces. */ diff --git a/sys.c b/sys.c index 65e4143dbd43940655ef3bc6d0f4fdaaff182dfe..e39aa4faa3ba817a6c569c81ce47ba63d4066d1c 100644 --- a/sys.c +++ b/sys.c @@ -79,7 +79,8 @@ struct oop_source_sys { sys_file *files; }; -struct oop_source_sys *sys_sig_owner[OOP_NUM_SIGNALS]; +static struct oop_source_sys *sys_sig_owner[OOP_NUM_SIGNALS]; +static int use_sa_restart = 0; static oop_source_sys *verify_source(oop_source *source) { oop_source_sys *sys = (oop_source_sys *) source; @@ -221,6 +222,7 @@ static void sys_on_signal(oop_source *source,int sig, #ifdef SA_NODEFER /* BSD/OS doesn't have this, for one. */ act.sa_flags &= ~SA_NODEFER; #endif + if (use_sa_restart) act.sa_flags |= SA_RESTART; sigaction(sig,&act,NULL); } } @@ -280,6 +282,13 @@ oop_source_sys *oop_sys_new(void) { return source; } +void oop_sys_use_sa_restart(void) { + int i; + for (i = 0; i < OOP_NUM_SIGNALS; ++i) + assert(NULL == sys_sig_owner[i] && "signal handler already registered"); + use_sa_restart = 1; +} + static void *sys_time_run(oop_source_sys *sys) { void *ret = OOP_CONTINUE; while (OOP_CONTINUE == ret && NULL != sys->time_run) {