Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unblock synchronous read on boost::asio::serial_port

I have a boost::thread which performs synchronous reads on a boost::asio::serial_port. When I destroy an instance of the class which contains both, I want the thread to end gracefully even if its blocked in a read call. How can I do this?

Looking at the docs, I tried cancel, but it works only for asynchronous reads/writes. Then I tried close, but I got an exception and it wasn't the kind you can recover from. Perhaps using send_break or native_handle? (this is Windows and portability's not critical)

Update: I also tried to stop the io_service I passed to the serial port object's constructor, but the read wasn't unblocked.

Edit: The exception is actually "catchable", but I'd hate to put a try/catch block inside a destructor, and refactoring the code to do the shutdown process outside the destructor would trigger lots of changes in upper layers. So I'd only go for this solution if some Boost authority says there is no other way.

like image 746
dario_ramos Avatar asked Feb 08 '12 19:02

dario_ramos


2 Answers

There is no way to unblock the synchronous read as you ask to.

There are two options:

  • close/shutdown the port and catch an exception, which was raised
  • use asynchronous reads and cancel them, when you shutdown your application

The first one, of course, is not a good idea, because you cannot distinguish terminating application from error.

like image 120
Rafał Rawicki Avatar answered Oct 25 '22 15:10

Rafał Rawicki


On close, you say that you get an exception that 'wasn't the kind you can recover from'.

What does this mean?

The solution seems to be to catch the exception. Why cannot you do that?

For the case when you want to distinguish between an error and program termination, set a flag on program termination before the close. In the exception handler ( catch ) check the flag. If set, handle as program termination, else handle as error.

You say that you do not wish to place a try/catch block inside a destructor. This seems like an odd prejudice to me, but OK there are other ways.

  1. You can allow the exception to propagate all the way to the topmost catch block that surrounds all your code, and handle it there. ( You do have such a try/catch block protecting your entire application, of course :-)

  2. Other ways are also possible ... but boss just dropped by

like image 42
ravenspoint Avatar answered Oct 25 '22 14:10

ravenspoint