Skip to content

Commit 04a7bae

Browse files
committed
wasm: support //go:wasmexport functions after a call to time.Sleep
This fixes a bug where `//go:wasmexport` functions would not be allowed anymore after a call to `time.Sleep` (when using `-buildmode=default`).
1 parent 8ff97bd commit 04a7bae

File tree

4 files changed

+20
-26
lines changed

4 files changed

+20
-26
lines changed

src/runtime/runtime_wasmentry.go

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,22 @@ import (
1414
// This is the _start entry point, when using -buildmode=default.
1515
func wasmEntryCommand() {
1616
// These need to be initialized early so that the heap can be initialized.
17+
initializeCalled = true
1718
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
1819
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
19-
wasmExportState = wasmExportStateInMain
2020
run()
21-
wasmExportState = wasmExportStateExited
22-
beforeExit()
21+
if mainExited {
22+
beforeExit()
23+
}
2324
}
2425

2526
// This is the _initialize entry point, when using -buildmode=c-shared.
2627
func wasmEntryReactor() {
2728
// This function is called before any //go:wasmexport functions are called
2829
// to initialize everything. It must not block.
2930

31+
initializeCalled = true
32+
3033
// Initialize the heap.
3134
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
3235
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
@@ -38,38 +41,23 @@ func wasmEntryReactor() {
3841
// goroutine.
3942
go func() {
4043
initAll()
41-
wasmExportState = wasmExportStateReactor
4244
}()
4345
scheduler(true)
44-
if wasmExportState != wasmExportStateReactor {
45-
// Unlikely, but if package initializers do something blocking (like
46-
// time.Sleep()), that's a bug.
47-
runtimePanic("package initializer blocks")
48-
}
4946
} else {
5047
// There are no goroutines (except for the main one, if you can call it
5148
// that), so we can just run all the package initializers.
5249
initAll()
53-
wasmExportState = wasmExportStateReactor
5450
}
5551
}
5652

57-
// Track which state we're in: before (or during) init, running inside
58-
// main.main, after main.main returned, or reactor mode (after init).
59-
var wasmExportState uint8
60-
61-
const (
62-
wasmExportStateInit = iota
63-
wasmExportStateInMain
64-
wasmExportStateExited
65-
wasmExportStateReactor
66-
)
53+
// Whether the runtime was initialized by a call to _initialize or _start.
54+
var initializeCalled bool
6755

6856
func wasmExportCheckRun() {
69-
switch wasmExportState {
70-
case wasmExportStateInit:
57+
switch {
58+
case !initializeCalled:
7159
runtimePanic("//go:wasmexport function called before runtime initialization")
72-
case wasmExportStateExited:
60+
case mainExited:
7361
runtimePanic("//go:wasmexport function called after main.main returned")
7462
}
7563
}

src/runtime/scheduler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const schedulerDebug = false
2121
// queue a new scheduler invocation using setTimeout.
2222
const asyncScheduler = GOOS == "js"
2323

24-
var schedulerDone bool
24+
var mainExited bool
2525

2626
// Queues used by the scheduler.
2727
var (
@@ -166,7 +166,7 @@ func removeTimer(tim *timer) bool {
166166
func scheduler(returnAtDeadlock bool) {
167167
// Main scheduler loop.
168168
var now timeUnit
169-
for !schedulerDone {
169+
for !mainExited {
170170
scheduleLog("")
171171
scheduleLog(" schedule")
172172
if sleepQueue != nil || timerQueue != nil {

src/runtime/scheduler_any.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func run() {
2323
go func() {
2424
initAll()
2525
callMain()
26-
schedulerDone = true
26+
mainExited = true
2727
}()
2828
scheduler(false)
2929
}

testdata/wasmexport-noscheduler.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package main
22

3+
import "time"
4+
35
func init() {
46
println("called init")
57
}
@@ -8,6 +10,10 @@ func init() {
810
func callTestMain()
911

1012
func main() {
13+
// Check that exported functions can still be called after calling
14+
// time.Sleep.
15+
time.Sleep(time.Millisecond)
16+
1117
// main.main is not used when using -buildmode=c-shared.
1218
callTestMain()
1319
}

0 commit comments

Comments
 (0)