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) {