Browse Source

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 years ago
parent
commit
6faabfb09c
1 changed files with 8 additions and 6 deletions
  1. 8 6
      source/Linux.Unix.Mod

+ 8 - 6
source/Linux.Unix.Mod

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