aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2023-02-22 17:44:34 +0100
committerRon Evans <[email protected]>2023-02-26 22:42:24 +0100
commit8bf94b92316c44a3110667d52bcb92f22f6c2923 (patch)
tree8cc3a9b284099b904d31b43e43ee32c82a9fefcc
parent488174767b13912e1ccc239053c47481cf8cb4da (diff)
downloadtinygo-8bf94b92316c44a3110667d52bcb92f22f6c2923.tar.gz
tinygo-8bf94b92316c44a3110667d52bcb92f22f6c2923.zip
internal/task: disallow blocking inside an interrupt
Blocking inside an interrupt is always unsafe and will lead to all kinds of bad behavior (even if it might appear to work sometimes). So disallow it, just like allocating heap memory inside an interrupt is not allowed. I suspect this will usually be caused by channel sends, like this: ch <- someValue The easy workaround is to make it a non-blocking send instead: select { case ch <- someValue: default: } This does mean the application might become a bit more complex to be able to deal with this case, but the alternative (undefined behavior) is IMHO much worse.
-rw-r--r--src/internal/task/task_stack.go8
1 files changed, 7 insertions, 1 deletions
diff --git a/src/internal/task/task_stack.go b/src/internal/task/task_stack.go
index ed938a63a..81e0f9ad7 100644
--- a/src/internal/task/task_stack.go
+++ b/src/internal/task/task_stack.go
@@ -2,7 +2,10 @@
package task
-import "unsafe"
+import (
+ "runtime/interrupt"
+ "unsafe"
+)
//go:linkname runtimePanic runtime.runtimePanic
func runtimePanic(str string)
@@ -45,6 +48,9 @@ func Pause() {
if *currentTask.state.canaryPtr != stackCanary {
runtimePanic("goroutine stack overflow")
}
+ if interrupt.In() {
+ runtimePanic("blocked inside interrupt")
+ }
currentTask.state.pause()
}