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 năm trước cách đây
mục cha
commit
6faabfb09c
1 tập tin đã thay đổi với 8 bổ sung6 xóa
  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) );