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

Dji Tello Halt does not terminate all the related goroutines and may wait forever when it is called multiple times #793

Open
st-user opened this issue May 25, 2021 · 2 comments
Labels

Comments

@st-user
Copy link
Contributor

st-user commented May 25, 2021

(parent commit 27c76b4585807e829965ec6a4551cadc28f430fe)

I tried Dji Tello Driver and found the following two problem related to Halt method.

If these are issues that need to be fixed, I’d like to make a pull request.

Problems

1. Halt stops only one of the three infinite loops.

The Driver runs the three infinite loops(*). However Halt stops only one of the three because:

  • case <- d.doneCh: break… is defined in two of the three.
  • Halt calls d.doneCh <- struct{}{} only once.

(*)

So, only one of the three infinite loops can read d.doneCh and stop.

2. Halt may wait forever when it is called multiple times.

Simply because Halt is blocked by d.doneCh <- struct{}{}, if we call Halt after the driver has been halted, It blocked forever.

My test case and bug fixes

Test case

The test cases below simulate the problems.
These two test methods don't stop.
(st-user@1ffc138)

// Only output one line ('Done routine x.')
func TestHaltShouldTerminateAllTheRelatedGoroutines(t *testing.T) {
	d := NewDriver("8888")
	d.cmdConn = &WriteCloserDoNothing{}

	var wg sync.WaitGroup
	wg.Add(3)
	go func() {
		<-d.doneCh
		wg.Done()
		fmt.Println("Done routine 1.")
	}()
	go func() {
		<-d.doneCh
		wg.Done()
		fmt.Println("Done routine 2.")
	}()
	go func() {
		<-d.doneCh
		wg.Done()
		fmt.Println("Done routine 3.")
	}()

	d.Halt()
	wg.Wait()
}

func TestHaltNotWaitForeverWhenCalledMultipleTimes(t *testing.T) {
	d := NewDriver("8888")
	d.cmdConn = &WriteCloserDoNothing{}

	d.Halt()
	d.Halt()
	d.Halt()
}

Try fixing

I tried fixing the problems at the commit(st-user@8c5ac6f) by:

  • Defining case <- d.doneCh: break… in every infinite loops.
  • Calling d.doneCh <- struct{}{} as many times as the running infinite loops.
@joeyberkovitz
Copy link
Contributor

On this topic, NewDriverWithIP doesn't initialize the doneCh (https://github.com/hybridgroup/gobot/blob/dev/platforms/dji/tello/driver.go#L238), so Halt is guaranteed to hang due to writing to a nil channel. I can submit a PR if needed to fix that function as well, although it's a trivial change

@gen2thomas
Copy link
Collaborator

Hi @joeyberkovitz thanks for pointing this out. A PR would be great.

Thanks!

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

No branches or pull requests

3 participants