Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix race condition when stopping before spinner fully built #3

Merged
merged 1 commit into from
Jun 18, 2018

Conversation

dnmurray
Copy link
Contributor

@dnmurray dnmurray commented Jun 9, 2018

We're running into a race condition that is fairly repeatable:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x1072502]

goroutine 1 [running]:
time.(*Ticker).Stop(0x0)
    /usr/local/go/src/time/tick.go:46 +0x22
github.com/phase2/rig/vendor/github.com/slok/gospinner.(*Spinner).Stop(0xc4200a83c0, 0x0, 0x0)
    /go/src/github.com/phase2/rig/vendor/github.com/slok/gospinner/spinner.go:197 +0xe6
github.com/phase2/rig/vendor/github.com/slok/gospinner.(*Spinner).FinishWithMessage(0xc4200a83c0, 0xc420089b60, 0xc, 0xc420086c60, 0x23, 0x3, 0xc4201336e0)
    /go/src/github.com/phase2/rig/vendor/github.com/slok/gospinner/spinner.go:240 +0x40
github.com/phase2/rig/vendor/github.com/slok/gospinner.(*Spinner).FinishWithSymbol(0xc4200a83c0, 0xc420089b60, 0xc, 0x0, 0x0)
    /go/src/github.com/phase2/rig/vendor/github.com/slok/gospinner/spinner.go:235 +0x51
github.com/phase2/rig/vendor/github.com/slok/gospinner.(*Spinner).Warn(0xc4200a83c0, 0xc420086c60, 0x23)
    /go/src/github.com/phase2/rig/vendor/github.com/slok/gospinner/spinner.go:220 +0x8a

I think moving the creation of the timer out of the goroutine will solve the problem.

phase2/rig#160

@dnmurray
Copy link
Contributor Author

dnmurray commented Jun 10, 2018

I'm not seeing what the failure is. master also fails (on my local env):

gospinner$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
gospinner$ go test -v ./
=== RUN   TestIntegrationStartNoColor
--- PASS: TestIntegrationStartNoColor (1.78s)
=== RUN   TestIntegrationStartDefault
--- FAIL: TestIntegrationStartDefault (1.78s)
	spinner_i_test.go:62: {kind:0 startMessage:This is a test color:96 want:|◐ This is a test|◓ This is a test|◑ This is a test|◒ This is a test}
		 - Wrong result, got: |◐ This is a test|◓ This is a test|◑ This is a test|◒ This is a test, want: |◐ This is a test|◓ This is a test|◑ This is a test|◒ This is a test
	spinner_i_test.go:62: {kind:5 startMessage:This is another test color:35 want:|⠋ This is another test|⠙ This is another test|⠹ This is another test|⠸ This is another test|⠼ This is another test|⠴ This is another test|⠦ This is another test|⠧ This is another test|⠇ This is another test|⠏ This is another test}
		 - Wrong result, got: |⠋ This is another test|⠙ This is another test|⠹ This is another test|⠸ This is another test|⠼ This is another test|⠴ This is another test|⠦ This is another test|⠧ This is another test|⠇ This is another test|⠏ This is another test, want: |⠋ This is another test|⠙ This is another test|⠹ This is another test|⠸ This is another test|⠼ This is another test|⠴ This is another test|⠦ This is another test|⠧ This is another test|⠇ This is another test|⠏ This is another test
	spinner_i_test.go:62: {kind:13 startMessage:Это тест color:92 want:|[    ] Это тест|[   =] Это тест|[  ==] Это тест|[ ===] Это тест|[====] Это тест|[=== ] Это тест|[==  ] Это тест|[=   ] Это тест}
		 - Wrong result, got: |[    ] Это тест|[   =] Это тест|[  ==] Это тест|[ ===] Это тест|[====] Это тест|[=== ] Это тест|[==  ] Это тест|[=   ] Это тест, want: |[    ] Это тест|[   =] Это тест|[  ==] Это тест|[ ===] Это тест|[====] Это тест|[=== ] Это тест|[==  ] Это тест|[=   ] Это тест
=== RUN   TestIntegrationStartColor
--- FAIL: TestIntegrationStartColor (1.78s)
	spinner_i_test.go:92: {kind:0 startMessage:This is a test color:96 want:|◐ This is a test|◓ This is a test|◑ This is a test|◒ This is a test}
		 - Wrong result, got: |◐ This is a test|◓ This is a test|◑ This is a test|◒ This is a test, want: |◐ This is a test|◓ This is a test|◑ This is a test|◒ This is a test
	spinner_i_test.go:92: {kind:5 startMessage:This is another test color:35 want:|⠋ This is another test|⠙ This is another test|⠹ This is another test|⠸ This is another test|⠼ This is another test|⠴ This is another test|⠦ This is another test|⠧ This is another test|⠇ This is another test|⠏ This is another test}
		 - Wrong result, got: |⠋ This is another test|⠙ This is another test|⠹ This is another test|⠸ This is another test|⠼ This is another test|⠴ This is another test|⠦ This is another test|⠧ This is another test|⠇ This is another test|⠏ This is another test, want: |⠋ This is another test|⠙ This is another test|⠹ This is another test|⠸ This is another test|⠼ This is another test|⠴ This is another test|⠦ This is another test|⠧ This is another test|⠇ This is another test|⠏ This is another test
	spinner_i_test.go:92: {kind:13 startMessage:Это тест color:92 want:|[    ] Это тест|[   =] Это тест|[  ==] Это тест|[ ===] Это тест|[====] Это тест|[=== ] Это тест|[==  ] Это тест|[=   ] Это тест}
		 - Wrong result, got: |[    ] Это тест|[   =] Это тест|[  ==] Это тест|[ ===] Это тест|[====] Это тест|[=== ] Это тест|[==  ] Это тест|[=   ] Это тест, want: |[    ] Это тест|[   =] Это тест|[  ==] Это тест|[ ===] Это тест|[====] Это тест|[=== ] Это тест|[==  ] Это тест|[=   ] Это тест
=== RUN   TestIntegrationStartWithSpeed
--- PASS: TestIntegrationStartWithSpeed (0.46s)
=== RUN   TestCorrectCreation
--- PASS: TestCorrectCreation (0.00s)
=== RUN   TestStartMultipleTimes
--- PASS: TestStartMultipleTimes (0.00s)
=== RUN   TestCreateFrames
--- PASS: TestCreateFrames (0.00s)
=== RUN   TestRender
--- PASS: TestRender (0.00s)
=== RUN   TestRenderError
--- PASS: TestRenderError (0.00s)
=== RUN   TestRenderColor
--- FAIL: TestRenderColor (0.00s)
	spinner_test.go:130: {kind:0 startMessage:This is a test color:96 WantFrames:[◐ This is a test ◓ This is a test ◑ This is a test ◒ This is a test]}
◐ This is a test, want: ◐ This is a testot:
	spinner_test.go:130: {kind:0 startMessage:This is a test color:96 WantFrames:[◐ This is a test ◓ This is a test ◑ This is a test ◒ This is a test]}
◓ This is a test, want: ◓ This is a test got:
	spinner_test.go:130: {kind:0 startMessage:This is a test color:96 WantFrames:[◐ This is a test ◓ This is a test ◑ This is a test ◒ This is a test]}
◑ This is a test, want: ◑ This is a testot:
	spinner_test.go:130: {kind:0 startMessage:This is a test color:96 WantFrames:[◐ This is a test ◓ This is a test ◑ This is a test ◒ This is a test]}
◒ This is a test, want: ◒ This is a test got:
	spinner_test.go:130: {kind:5 startMessage:This is another test color:35 WantFrames:[⠋ This is another test ⠙ This is another test ⠹ This is another test ⠸ This is another test ⠼ This is another test ⠴ This is another test ⠦ This is another test ⠧ This is another test ⠇ This is another test ⠏ This is another test]}
⠋ This is another test, want: ⠋ This is another test
	spinner_test.go:130: {kind:5 startMessage:This is another test color:35 WantFrames:[⠋ This is another test ⠙ This is another test ⠹ This is another test ⠸ This is another test ⠼ This is another test ⠴ This is another test ⠦ This is another test ⠧ This is another test ⠇ This is another test ⠏ This is another test]}
⠙ This is another test, want: ⠙ This is another test
	spinner_test.go:130: {kind:5 startMessage:This is another test color:35 WantFrames:[⠋ This is another test ⠙ This is another test ⠹ This is another test ⠸ This is another test ⠼ This is another test ⠴ This is another test ⠦ This is another test ⠧ This is another test ⠇ This is another test ⠏ This is another test]}
⠹ This is another test, want: ⠹ This is another test
	spinner_test.go:130: {kind:5 startMessage:This is another test color:35 WantFrames:[⠋ This is another test ⠙ This is another test ⠹ This is another test ⠸ This is another test ⠼ This is another test ⠴ This is another test ⠦ This is another test ⠧ This is another test ⠇ This is another test ⠏ This is another test]}
⠸ This is another test, want: ⠸ This is another test
	spinner_test.go:130: {kind:5 startMessage:This is another test color:35 WantFrames:[⠋ This is another test ⠙ This is another test ⠹ This is another test ⠸ This is another test ⠼ This is another test ⠴ This is another test ⠦ This is another test ⠧ This is another test ⠇ This is another test ⠏ This is another test]}
⠼ This is another test, want: ⠼ This is another test
	spinner_test.go:130: {kind:5 startMessage:This is another test color:35 WantFrames:[⠋ This is another test ⠙ This is another test ⠹ This is another test ⠸ This is another test ⠼ This is another test ⠴ This is another test ⠦ This is another test ⠧ This is another test ⠇ This is another test ⠏ This is another test]}
⠴ This is another test, want: ⠴ This is another test
	spinner_test.go:130: {kind:5 startMessage:This is another test color:35 WantFrames:[⠋ This is another test ⠙ This is another test ⠹ This is another test ⠸ This is another test ⠼ This is another test ⠴ This is another test ⠦ This is another test ⠧ This is another test ⠇ This is another test ⠏ This is another test]}
⠦ This is another test, want: ⠦ This is another test
	spinner_test.go:130: {kind:5 startMessage:This is another test color:35 WantFrames:[⠋ This is another test ⠙ This is another test ⠹ This is another test ⠸ This is another test ⠼ This is another test ⠴ This is another test ⠦ This is another test ⠧ This is another test ⠇ This is another test ⠏ This is another test]}
⠧ This is another test, want: ⠧ This is another test
	spinner_test.go:130: {kind:5 startMessage:This is another test color:35 WantFrames:[⠋ This is another test ⠙ This is another test ⠹ This is another test ⠸ This is another test ⠼ This is another test ⠴ This is another test ⠦ This is another test ⠧ This is another test ⠇ This is another test ⠏ This is another test]}
⠇ This is another test, want: ⠇ This is another test
	spinner_test.go:130: {kind:5 startMessage:This is another test color:35 WantFrames:[⠋ This is another test ⠙ This is another test ⠹ This is another test ⠸ This is another test ⠼ This is another test ⠴ This is another test ⠦ This is another test ⠧ This is another test ⠇ This is another test ⠏ This is another test]}
⠏ This is another test, want: ⠏ This is another test
	spinner_test.go:130: {kind:13 startMessage:Это тест color:92 WantFrames:[[    ] Это тест [   =] Это тест [  ==] Это тест [ ===] Это тест [====] Это тест [=== ] Это тест [==  ] Это тест [=   ] Это тест]}
[    ] Это тест, want: [    ] Это тест
	spinner_test.go:130: {kind:13 startMessage:Это тест color:92 WantFrames:[[    ] Это тест [   =] Это тест [  ==] Это тест [ ===] Это тест [====] Это тест [=== ] Это тест [==  ] Это тест [=   ] Это тест]}
[   =] Это тест, want: [   =] Это тест
	spinner_test.go:130: {kind:13 startMessage:Это тест color:92 WantFrames:[[    ] Это тест [   =] Это тест [  ==] Это тест [ ===] Это тест [====] Это тест [=== ] Это тест [==  ] Это тест [=   ] Это тест]}
[  ==] Это тест, want: [  ==] Это тест
	spinner_test.go:130: {kind:13 startMessage:Это тест color:92 WantFrames:[[    ] Это тест [   =] Это тест [  ==] Это тест [ ===] Это тест [====] Это тест [=== ] Это тест [==  ] Это тест [=   ] Это тест]}
[ ===] Это тест, want: [ ===] Это тест
	spinner_test.go:130: {kind:13 startMessage:Это тест color:92 WantFrames:[[    ] Это тест [   =] Это тест [  ==] Это тест [ ===] Это тест [====] Это тест [=== ] Это тест [==  ] Это тест [=   ] Это тест]}
[====] Это тест, want: [====] Это тест
	spinner_test.go:130: {kind:13 startMessage:Это тест color:92 WantFrames:[[    ] Это тест [   =] Это тест [  ==] Это тест [ ===] Это тест [====] Это тест [=== ] Это тест [==  ] Это тест [=   ] Это тест]}
[=== ] Это тест, want: [=== ] Это тест
	spinner_test.go:130: {kind:13 startMessage:Это тест color:92 WantFrames:[[    ] Это тест [   =] Это тест [  ==] Это тест [ ===] Это тест [====] Это тест [=== ] Это тест [==  ] Это тест [=   ] Это тест]}
[==  ] Это тест, want: [==  ] Это тест
	spinner_test.go:130: {kind:13 startMessage:Это тест color:92 WantFrames:[[    ] Это тест [   =] Это тест [  ==] Это тест [ ===] Это тест [====] Это тест [=== ] Это тест [==  ] Это тест [=   ] Это тест]}
[=   ] Это тест, want: [=   ] Это тест
=== RUN   TestSetMessage
--- PASS: TestSetMessage (0.00s)
=== RUN   TestStop
--- PASS: TestStop (0.01s)
=== RUN   TestStopError
--- PASS: TestStopError (0.00s)
=== RUN   TestReset
--- PASS: TestReset (0.00s)
=== RUN   TestSucceed
--- PASS: TestSucceed (0.01s)
=== RUN   TestFail
--- PASS: TestFail (0.01s)
=== RUN   TestWarn
--- PASS: TestWarn (0.01s)
=== RUN   TestFinish
--- PASS: TestFinish (0.01s)
=== RUN   TestFinishWithSymbol
--- PASS: TestFinishWithSymbol (0.01s)
=== RUN   TestFinishWithMessage
--- PASS: TestFinishWithMessage (0.01s)
FAIL
FAIL	github.com/dnmurray/gospinner	5.891s
gospinner$ go version
go version go1.10.2 darwin/amd64
gospinner$

@slok
Copy link
Owner

slok commented Jun 10, 2018

Hi @dnmurray!

It's been a long time since I released this project. Yes, you are right that ticker could create a race condition because the mutex could be closed before assigning the ticker in the goroutine and calling stop before it's assigned making a Stop on a nil ticker.

Image for a better explanation:

As you say you can or move the ticker creation outside the goroutine (now is inside the mutex) or wrap the goroutine assignations with the mutex.

I'll take a look at the tests in the following days and fix them. I will notify you when I have found the problem with the color test.

Thanks and sorry for the error :(

@dnmurray
Copy link
Contributor Author

@slok Thanks for the reply, and the library!

@slok
Copy link
Owner

slok commented Jun 14, 2018

Fixed in #4 You can rebase over master and try again! :)

@dnmurray dnmurray force-pushed the bug/stop-race-condition branch from 97aaa2e to 7897291 Compare June 17, 2018 18:47
@dnmurray
Copy link
Contributor Author

Updated, passing. Thanks for the fixes.

@slok slok merged commit c6cc8e2 into slok:master Jun 18, 2018
@dnmurray
Copy link
Contributor Author

@slok Could you please cut a new release tag? We're using dep to manage dependencies in our project.

@slok
Copy link
Owner

slok commented Jun 19, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants