tinygo icon indicating copy to clipboard operation
tinygo copied to clipboard

goroutines.go may be flaky

Open QuLogic opened this issue 9 months ago • 6 comments

Once it failed as TestBuild/ARMLinux/goroutines.go, and once as TestBuild/X86Linux/goroutines.go, but it was the same diff:

=== NAME  TestBuild/ARMLinux/goroutines.go
    main_test.go:874: output did not match (expected 523 bytes, got 523 bytes):
    main_test.go:875: diff expected actual
        --- expected
        +++ actual
        @@ -2,8 +2,8 @@
         goroutine in init
         main 1
         sub 1
        -main 2
         sub 2
        +main 2
         main 3
         wait:
           wait start
        
    main_test.go:477: stdout: init
    main_test.go:477: stdout: goroutine in init
    main_test.go:477: stdout: main 1
    main_test.go:477: stdout: sub 1
    main_test.go:477: stdout: sub 2
    main_test.go:477: stdout: main 2
    main_test.go:477: stdout: main 3
    main_test.go:477: stdout: wait:
    main_test.go:477: stdout:   wait start
    main_test.go:477: stdout:   wait end
    main_test.go:477: stdout: end waiting
    main_test.go:477: stdout: value produced after some time: 42
    main_test.go:477: stdout: non-blocking goroutine
    main_test.go:477: stdout: done with non-blocking goroutine
    main_test.go:477: stdout: async interface method call
    main_test.go:477: stdout: slept inside func pointer 8
    main_test.go:477: stdout: slept inside closure, with value: 20 8
    main_test.go:477: stdout: closure go call result: 1
    main_test.go:477: stdout: pre-acquired mutex
    main_test.go:477: stdout: releasing mutex
    main_test.go:477: stdout: acquired mutex from goroutine
    main_test.go:477: stdout: releasing mutex from goroutine
    main_test.go:477: stdout: re-acquired mutex
    main_test.go:477: stdout: done
    main_test.go:477: stdout: called: Foo.Nowait
    main_test.go:477: stdout: called: Foo.Wait
    main_test.go:477: stdout:   ...waited
    main_test.go:477: stdout: done with 'go on interface'
    main_test.go:477: stdout: paddedStruct: 5 7

I did apply #4958, but that is in a later part of the test, so didn't fix it.

QuLogic avatar Jul 20 '25 07:07 QuLogic

Could be related to #4963 since this test also has timers.

QuLogic avatar Jul 20 '25 07:07 QuLogic

A different, but probably the same, failure:

=== NAME  TestBuild/ARM64Linux/goroutines.go
    main_test.go:308: output did not match (expected 523 bytes, got 523 bytes):
    main_test.go:308: diff expected actual
        --- expected
        +++ actual
        @@ -13,8 +13,8 @@
         non-blocking goroutine
         done with non-blocking goroutine
         async interface method call
        -slept inside func pointer 8
         slept inside closure, with value: 20 8
        +slept inside func pointer 8
         closure go call result: 1
         pre-acquired mutex
         releasing mutex
        
    main_test.go:308: stdout: init
    main_test.go:308: stdout: goroutine in init
    main_test.go:308: stdout: main 1
    main_test.go:308: stdout: sub 1
    main_test.go:308: stdout: main 2
    main_test.go:308: stdout: sub 2
    main_test.go:308: stdout: main 3
    main_test.go:308: stdout: wait:
    main_test.go:308: stdout:   wait start
    main_test.go:308: stdout:   wait end
    main_test.go:308: stdout: end waiting
    main_test.go:308: stdout: value produced after some time: 42
    main_test.go:308: stdout: non-blocking goroutine
    main_test.go:308: stdout: done with non-blocking goroutine
    main_test.go:308: stdout: async interface method call
    main_test.go:308: stdout: slept inside closure, with value: 20 8
    main_test.go:308: stdout: slept inside func pointer 8
    main_test.go:308: stdout: closure go call result: 1
    main_test.go:308: stdout: pre-acquired mutex
    main_test.go:308: stdout: releasing mutex
    main_test.go:308: stdout: acquired mutex from goroutine
    main_test.go:308: stdout: releasing mutex from goroutine
    main_test.go:308: stdout: re-acquired mutex
    main_test.go:308: stdout: done
    main_test.go:308: stdout: called: Foo.Nowait
    main_test.go:308: stdout: called: Foo.Wait
    main_test.go:308: stdout:   ...waited
    main_test.go:308: stdout: done with 'go on interface'
    main_test.go:308: stdout: paddedStruct: 5 7

QuLogic avatar Jul 21 '25 06:07 QuLogic

FWIW, I de-flaked this test in https://github.com/tinygo-org/tinygo/pull/4958. It seems to me prints may introduce scheduling points and as such need similar channel-based synchronization.

eliasnaur avatar Jul 21 '25 12:07 eliasnaur

Yes, I applied that patch, but it's unfortunately not enough.

QuLogic avatar Aug 02 '25 22:08 QuLogic

What I meant was that a similar fix will be needed for this issue, not that #4958 fixes it.

eliasnaur avatar Aug 03 '25 13:08 eliasnaur

For this I'd prefer sync.WaitGroup over channels since sync.WaitGroup is much more low level and less likely to interfere with what the test is actually trying to test.

Or, we can increase the delay. See: https://github.com/tinygo-org/tinygo/pull/4982

aykevl avatar Sep 29 '25 13:09 aykevl