瀏覽代碼

Exit threads by explicitly jumping to end of thread start routine by storing the address of a jmp_buf in thread-local memory

The function pthread_exit throws an exception in order to return to the caller of the thread routine but sometimes fails to unwind Oberon stack frames which causes an abort of the entire process.

git-svn-id: https://svn-dept.inf.ethz.ch/svn/lecturers/a2/trunk@8810 8c9fc860-2736-0410-a75d-ab315db34111
negelef 6 年之前
父節點
當前提交
6faabfb09c
共有 1 個文件被更改,包括 8 次插入6 次删除
  1. 8 6
      source/Linux.Unix.Mod

+ 8 - 6
source/Linux.Unix.Mod

@@ -458,6 +458,7 @@ VAR
 	suspend_done: LONGINT;
 	suspend_done: LONGINT;
 	resume_done: LONGINT;
 	resume_done: LONGINT;
 	sasuspend, saresume: Sigaction;
 	sasuspend, saresume: Sigaction;
+	thread_exit: Key_t;
 
 
 	argc-: LONGINT;  argv-: ADDRESS;  environ-: ADDRESS;
 	argc-: LONGINT;  argv-: ADDRESS;  environ-: ADDRESS;
 
 
@@ -481,7 +482,6 @@ VAR
 	pthread_cond_signal: PROCEDURE {C} (cond: ADDRESS): WORD;
 	pthread_cond_signal: PROCEDURE {C} (cond: ADDRESS): WORD;
 
 
 	pthread_create-: PROCEDURE {C} (newthread: ADDRESS; attr: ADDRESS; start_routine: ADDRESS; arg: PROCEDURE): WORD;
 	pthread_create-: PROCEDURE {C} (newthread: ADDRESS; attr: ADDRESS; start_routine: ADDRESS; arg: PROCEDURE): WORD;
-	pthread_exit-: PROCEDURE {C, NORETURN} (thr: ADDRESS);
 	pthread_detach: PROCEDURE {C} (thr: ADDRESS);
 	pthread_detach: PROCEDURE {C} (thr: ADDRESS);
 	pthread_kill: PROCEDURE {C} (thr: ADDRESS; sigid: LONGINT): LONGINT;
 	pthread_kill: PROCEDURE {C} (thr: ADDRESS; sigid: LONGINT): LONGINT;
 	pthread_cancel: PROCEDURE {C} (thr: ADDRESS);
 	pthread_cancel: PROCEDURE {C} (thr: ADDRESS);
@@ -715,7 +715,7 @@ VAR
 
 
 	PROCEDURE ThrExit*( );
 	PROCEDURE ThrExit*( );
 	BEGIN {UNCOOPERATIVE, UNCHECKED}
 	BEGIN {UNCOOPERATIVE, UNCHECKED}
-		pthread_exit( 0 );
+		siglongjmp (pthread_getspecific (thread_exit), 1);
 	END ThrExit;
 	END ThrExit;
 
 
 	PROCEDURE ThrSetPriority*(thr: Thread_t; prio: LONGINT);
 	PROCEDURE ThrSetPriority*(thr: Thread_t; prio: LONGINT);
@@ -748,6 +748,7 @@ VAR
 		attr: PThreadAttr;
 		attr: PThreadAttr;
 		stack: Stack;
 		stack: Stack;
 		size: SIZE;
 		size: SIZE;
+		state: ARRAY 2048 OF CHAR;
 	BEGIN {UNCOOPERATIVE, UNCHECKED}
 	BEGIN {UNCOOPERATIVE, UNCHECKED}
 		me := pthread_self();
 		me := pthread_self();
 
 
@@ -779,9 +780,9 @@ VAR
 		res := pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NIL );
 		res := pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NIL );
 		param.sched_priority := 0;
 		param.sched_priority := 0;
 		res := pthread_setschedparam( me, SCHED_OTHER, ADDRESS OF param );
 		res := pthread_setschedparam( me, SCHED_OTHER, ADDRESS OF param );
-		proc();
 
 
-		pthread_exit( NIL );
+		ASSERT (pthread_setspecific (thread_exit, ADDRESS OF state) = 0);
+		IF sigsetjmp (ADDRESS OF state, 0) = 0 THEN proc END;
 		RETURN NIL;
 		RETURN NIL;
 	END Starter;
 	END Starter;
 
 
@@ -823,7 +824,7 @@ VAR
 		IF (thr # mainthread) THEN
 		IF (thr # mainthread) THEN
 	    		pthread_detach( thr );
 	    		pthread_detach( thr );
     			IF (thr = pthread_self()) THEN
     			IF (thr = pthread_self()) THEN
-				pthread_exit( 0 );
+				ThrExit;
 			ELSE
 			ELSE
 				pthread_cancel( thr );
 				pthread_cancel( thr );
 			END
 			END
@@ -898,6 +899,8 @@ VAR
 		saresume.sa_handler := resume_handler;
 		saresume.sa_handler := resume_handler;
 		ASSERT(sigaction( T_SIGRESUME, ADDRESS OF saresume, NIL ) = 0);
 		ASSERT(sigaction( T_SIGRESUME, ADDRESS OF saresume, NIL ) = 0);
 
 
+		ASSERT (pthread_key_create (ADDRESS OF thread_exit, NIL) = 0);
+
 		RETURN TRUE;
 		RETURN TRUE;
 	END ThrInitialize;
 	END ThrInitialize;
 
 
@@ -1156,7 +1159,6 @@ VAR
 		Dlsym( libc, "pthread_cond_signal", ADDRESSOF(pthread_cond_signal) );
 		Dlsym( libc, "pthread_cond_signal", ADDRESSOF(pthread_cond_signal) );
 
 
 		Dlsym( libp, "pthread_create", ADDRESSOF(pthread_create) );
 		Dlsym( libp, "pthread_create", ADDRESSOF(pthread_create) );
-		Dlsym( libp, "pthread_exit", ADDRESSOF(pthread_exit) );
 		Dlsym( libp, "pthread_detach", ADDRESSOF(pthread_detach) );
 		Dlsym( libp, "pthread_detach", ADDRESSOF(pthread_detach) );
 		Dlsym( libp, "pthread_cancel", ADDRESSOF(pthread_cancel) );
 		Dlsym( libp, "pthread_cancel", ADDRESSOF(pthread_cancel) );
 		Dlsym( libp, "pthread_kill", ADDRESSOF(pthread_kill) );
 		Dlsym( libp, "pthread_kill", ADDRESSOF(pthread_kill) );