Re: Re no blocking wait on Linux

From: Tom Hughes (thh_at_cyberscience.com)
Date: Mon Jan 14 2002 - 09:50:50 GMT


In message <200201111853.KAA28214_at_hunter>
        Rod Armstrong <rod_at_san-jose.tt.slb.com> wrote:

> On Linux, wait3() must be used in order to get interrupts. Maybe
> someone with a Redhat system could investigate.

I've found and solved the wait() problem now. In fact wait() does get
interrupts but the problem is that Linux blocks signals while they are
being handled and a longjmp() out of the signal handler does not
cancel that block, so after the first time SIGIO is blocked and we
don't get interrupted.

The solution is to use sigsetjmp() and siglongjmp() and set the
savesigs flag when calling sigsetjmp() so that the signal context
is restored when we jump out of the handler. The following patch 
does just that, and can be applied in place of my usleep() patch:

diff -ur ups-3.37-beta4/ups/ao_ptrace.c ups-wait/ups/ao_ptrace.c
--- ups-3.37-beta4/ups/ao_ptrace.c	Mon Jan  7 16:54:52 2002
+++ ups-wait/ups/ao_ptrace.c	Mon Jan 14 09:45:24 2002
@@ -75,7 +75,11 @@
 static int Last_attach_pid; 
 
 /* Used by 'stop_target()'. */
+#ifdef OS_LINUX
+static sigjmp_buf Longjmp_env;
+#else
 static jmp_buf Longjmp_env;
+#endif
 
 
 static void stop_target PROTO((void));
@@ -174,7 +178,11 @@
 static void
 stop_target()
 {
+#ifdef OS_LINUX
+	siglongjmp(Longjmp_env, 1);
+#else
 	longjmp(Longjmp_env, 1);
+#endif
 }
 
 static int
@@ -182,17 +190,17 @@
 wait_arg_t *p_status;
 {
 	int ret;
+#ifdef OS_LINUX
+	if (sigsetjmp(Longjmp_env, 1) == 1)
+#else
 	if (setjmp(Longjmp_env) == 1)
+#endif
 		return 0;
 
-#ifdef OS_LINUX
-	ret = wait3(p_status, WNOHANG, NULL);
-#else
 	if (get_run_alarm_time() > 0)
 	    ret = wait3(p_status, WNOHANG, NULL);
 	else
 	    ret = wait(p_status);
-#endif
 
 	return ret;
 }

Tom

-- 
Tom Hughes (thh_at_cyberscience.com)
Software Engineer, Cyberscience Corporation
http://www.cyberscience.com/


This archive was generated by hypermail 2.1.4 : Wed Feb 13 2002 - 21:51:35 GMT