@@ -362,7 +362,12 @@ func signal_enable(s uint32) {
362362		// receivedSignals into a uint32 array. 
363363		runtimePanicAt (returnAddress (0 ), "unsupported signal number" )
364364	}
365+ 
366+ 	// This is intentonally a non-atomic store. This is safe, since hasSignals 
367+ 	// is only used in waitForEvents which is only called when there's a 
368+ 	// scheduler (and therefore there is no parallelism). 
365369	hasSignals  =  true 
370+ 
366371	// It's easier to implement this function in C. 
367372	tinygo_signal_enable (s )
368373}
@@ -391,6 +396,9 @@ func signal_disable(s uint32) {
391396func  signal_waitUntilIdle () {
392397	// Wait until signal_recv has processed all signals. 
393398	for  receivedSignals .Load () !=  0  {
399+ 		// TODO: this becomes a busy loop when using threads. 
400+ 		// We might want to pause until signal_recv has no more incoming signals 
401+ 		// to process. 
394402		Gosched ()
395403	}
396404}
@@ -434,7 +442,7 @@ func tinygo_signal_handler(s int32) {
434442
435443// Task waiting for a signal to arrive, or nil if it is running or there are no 
436444// signals. 
437- var  signalRecvWaiter  * task.Task 
445+ var  signalRecvWaiter  atomic. Pointer [ task.Task ] 
438446
439447//go:linkname signal_recv os/signal.signal_recv 
440448func  signal_recv () uint32  {
@@ -443,7 +451,10 @@ func signal_recv() uint32 {
443451		val  :=  receivedSignals .Load ()
444452		if  val  ==  0  {
445453			// There are no signals to receive. Sleep until there are. 
446- 			signalRecvWaiter  =  task .Current ()
454+ 			if  signalRecvWaiter .Swap (task .Current ()) !=  nil  {
455+ 				// We expect only a single goroutine to call signal_recv. 
456+ 				runtimePanic ("signal_recv called concurrently" )
457+ 			}
447458			task .Pause ()
448459			continue 
449460		}
@@ -474,10 +485,11 @@ func signal_recv() uint32 {
474485// Return true if it was reactivated (and therefore the scheduler should run 
475486// again), and false otherwise. 
476487func  checkSignals () bool  {
477- 	if  receivedSignals .Load () !=  0  &&  signalRecvWaiter  !=  nil  {
478- 		scheduleTask (signalRecvWaiter )
479- 		signalRecvWaiter  =  nil 
480- 		return  true 
488+ 	if  receivedSignals .Load () !=  0  {
489+ 		if  waiter  :=  signalRecvWaiter .Swap (nil ); waiter  !=  nil  {
490+ 			scheduleTask (waiter )
491+ 			return  true 
492+ 		}
481493	}
482494	return  false 
483495}
0 commit comments