Skip to content

Commit af4e171

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 af4e171

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-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: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,3 +289,25 @@ func TestGoroutineJsObject(t *testing.T) {
289289
runtime.Gosched()
290290
}
291291
}
292+
293+
func issue1106() {
294+
select {
295+
default:
296+
}
297+
}
298+
299+
func TestIssue1106(t *testing.T) {
300+
// https://github.com/gopherjs/gopherjs/issues/1106#issuecomment-1046323374
301+
done := false
302+
go func() {
303+
f := issue1106
304+
f()
305+
done = true
306+
}()
307+
308+
// Will get stuck here if #1106 is not fixed.
309+
for !done {
310+
// Maintain one active goroutine to prevent Node from exiting.
311+
runtime.Gosched()
312+
}
313+
}

0 commit comments

Comments
 (0)