@@ -74,7 +74,8 @@ void ServiceServerLink::cancelCall(const CallInfoPtr& info)
74
74
{
75
75
boost::mutex::scoped_lock lock (local->finished_mutex_ );
76
76
local->finished_ = true ;
77
- local->resp_ = nullptr ; // The response pointer is no longer valid
77
+ // If onResponse fires after we've returned from call() (due to this being cancelled), the pointer to resp_ will no longer be valid
78
+ local->resp_ = nullptr ;
78
79
local->finished_condition_ .notify_all ();
79
80
}
80
81
@@ -189,34 +190,6 @@ void ServiceServerLink::onRequestWritten(const ConnectionPtr& conn)
189
190
lock.unlock ();
190
191
191
192
connection_->read (5 , boost::bind (&ServiceServerLink::onResponseOkAndLength, this , boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3, boost::placeholders::_4));
192
-
193
- if (timeout_sec_ >= 0.0 )
194
- {
195
- boost::thread timeout_checker (
196
- boost::bind (
197
- &ServiceServerLink::waitForTimeout,
198
- this ,
199
- current_call,
200
- timeout_sec_));
201
- }
202
- }
203
-
204
- void ServiceServerLink::waitForTimeout (CallInfoPtr info, double seconds)
205
- {
206
- boost::mutex::scoped_lock finished_lock (info->finished_mutex_ );
207
- if (info && info->finished_condition_ .wait_for (finished_lock, boost::chrono::duration<double >(seconds)) == boost::cv_status::timeout)
208
- {
209
- bool finished = info->finished_ ;
210
- finished_lock.unlock ();
211
-
212
- // If we timeout, we need to cancel the call
213
- ROS_WARN_STREAM (" Service call to " << service_name_ << " timed out after " << seconds << " seconds" );
214
-
215
- if (info && !finished)
216
- {
217
- cancelCall (info);
218
- }
219
- }
220
193
}
221
194
222
195
void ServiceServerLink::onResponseOkAndLength (const ConnectionPtr& conn, const boost::shared_array<uint8_t >& buffer, uint32_t size, bool success)
@@ -400,23 +373,50 @@ bool ServiceServerLink::call(const SerializedMessage& req, SerializedMessage& re
400
373
processNextCall ();
401
374
}
402
375
376
+ auto status = boost::cv_status::no_timeout;
377
+
403
378
{
404
379
boost::mutex::scoped_lock lock (info->finished_mutex_ );
405
380
406
381
while (!info->finished_ )
407
382
{
408
- info->finished_condition_ .wait (lock);
383
+ if (timeout_sec_ >= 0.0 )
384
+ {
385
+ status = info->finished_condition_ .wait_for (lock, boost::chrono::duration<double >(timeout_sec_));
386
+
387
+ if (status == boost::cv_status::timeout)
388
+ {
389
+ bool finished = info->finished_ ;
390
+ lock.unlock ();
391
+
392
+ if (!finished)
393
+ {
394
+ cancelCall (info);
395
+ }
396
+
397
+ ROS_WARN_STREAM (" Service call to " << service_name_ << " timed out after " << timeout_sec_ << " seconds" );
398
+ }
399
+ }
400
+ else
401
+ {
402
+ info->finished_condition_ .wait (lock);
403
+ }
409
404
}
410
405
}
411
406
412
407
info->call_finished_ = true ;
413
408
409
+ if (status == boost::cv_status::timeout)
410
+ {
411
+ ROS_WARN_STREAM (" Service call to " << service_name_ << " timed out after " << timeout_sec_ << " seconds" );
412
+ }
413
+
414
414
if (info->exception_string_ .length () > 0 )
415
415
{
416
416
ROS_ERROR (" Service call failed: service [%s] responded with an error: %s" , service_name_.c_str (), info->exception_string_ .c_str ());
417
417
}
418
418
419
- return info->success_ ;
419
+ return info->success_ && status != boost::cv_status::timeout ;
420
420
}
421
421
422
422
bool ServiceServerLink::isValid () const
0 commit comments