Commit ce7f1e9
authored
stop producer on destruction (UniversalRobots#472)
When a TCP socket silently fails (e.g. network loss, cable pull) — where
no RST or FIN is delivered —
RTDEClient::~RTDEClient() hangs indefinitely.
The background read thread is inside tryGetImpl's inner while(true)
loop. stream_.read() returns EAGAIN every
~1 second due to the SO_RCVTIMEO set in setupProducer, but:
- !running_ is false (the producer was never stopped)
- stream_.getState() == SocketState::Connected is true (the kernel still
considers the socket connected — no
RST was received)
So the loop hits continue and spins indefinitely.
When stopBackgroundRead() is then called in the destructor, it sets
background_read_running_ = false and
calls join(). But background_read_running_ is only checked in the outer
loop of backgroundReadThreadFunc —
the thread is trapped inside tryGetImpl where only running_ (the
URProducer flag) controls exit. The join()
never returns.
The fix is to call prod_->stopProducer() before stopBackgroundRead().
This sets running_ = false, so within
at most one SO_RCVTIMEO interval (~1 second), tryGetImpl sees !running_
and returns, the background thread
exits its outer loop, and the join() completes immediately.
Note that disconnect() already does this correctly (stream_.disconnect()
+ prod_->stopProducer() +
stopBackgroundRead()), but in the destructor stopBackgroundRead() is
called before disconnect(), so the
producer is never stopped before the join is attempted.1 parent bd19a47 commit ce7f1e9
1 file changed
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
| 94 | + | |
94 | 95 | | |
95 | 96 | | |
96 | 97 | | |
| |||
0 commit comments