Skip to content

Commit fa09322

Browse files
committed
Prevent non-blocking select from making function appear blocking.
In almost every place compiler checks whether a function is blocking by checking `len(c.Blocking) > 0`, so assigning false to the map confuses the check, causing unnecessary checkpointing prologue and epilogue to be added to the function. Fixes #1106.
1 parent 6bee22a commit fa09322

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

compiler/statements.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,9 @@ func (fc *funcContext) translateStmt(stmt ast.Stmt, label *types.Label) {
520520
Fun: fc.newIdent("$select", types.NewSignature(nil, types.NewTuple(types.NewVar(0, nil, "", types.NewInterface(nil, nil))), types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int])), false)),
521521
Args: []ast.Expr{fc.newIdent(fmt.Sprintf("[%s]", strings.Join(channels, ", ")), types.NewInterface(nil, nil))},
522522
}, types.Typ[types.Int])
523-
fc.Blocking[selectCall] = !hasDefault
523+
if !hasDefault {
524+
fc.Blocking[selectCall] = true
525+
}
524526
fc.Printf("%s = %s;", selectionVar, fc.translateExpr(selectCall))
525527

526528
if len(caseClauses) != 0 {

tests/goroutine_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"runtime"
7+
"sync/atomic"
78
"testing"
89
"time"
910

@@ -289,3 +290,25 @@ func TestGoroutineJsObject(t *testing.T) {
289290
runtime.Gosched()
290291
}
291292
}
293+
294+
func issue1106() {
295+
select {
296+
default:
297+
}
298+
}
299+
300+
func TestIssue1106(t *testing.T) {
301+
// https://github.com/gopherjs/gopherjs/issues/1106#issuecomment-1046323374
302+
var done int32 = 0
303+
go func() {
304+
f := issue1106
305+
f()
306+
atomic.AddInt32(&done, 1)
307+
}()
308+
309+
// Will get stuck here if #1106 is not fixed.
310+
for !atomic.CompareAndSwapInt32(&done, 1, 1) {
311+
// Maintain one active goroutine to prevent Node from exiting.
312+
runtime.Gosched()
313+
}
314+
}

0 commit comments

Comments
 (0)