diff options
author | Aaron Rossetto <aaron.rossetto@ni.com> | 2021-08-30 12:12:30 -0500 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2021-08-31 07:32:41 -0500 |
commit | f8d8c23e701b5e1bc2c18d1a0f28b7a2699afbac (patch) | |
tree | cbbb8cf82a0064a6d2ddfa349f3737e2453ba2ff | |
parent | 919043f305efdd29fbdf586e9cde95d9507150e8 (diff) | |
download | uhd-f8d8c23e701b5e1bc2c18d1a0f28b7a2699afbac.tar.gz uhd-f8d8c23e701b5e1bc2c18d1a0f28b7a2699afbac.tar.bz2 uhd-f8d8c23e701b5e1bc2c18d1a0f28b7a2699afbac.zip |
uhd: transport: Avoid exceptions in disconnect_receiver()
inline_io_service::disconnect_receiver() uses the recv_link_if parameter
as a key into the _recv_tbl map. In some error cases, notably when an
underlying link timeout occurs when setting up a transport, that key may
not exist in the table. Attempting to index the table by that
non-existent key causes an std::out_of_range exception to be thrown.
However, in the aforementioned error case, disconnect_receiver() is
called as part of a destructor of an object that is in one of the stack
frames being unwound as the timeout exception is in flight. Throwing an
exception while one is in flight ultimately causes the C++ runtime to
terminate the process. (Generally, throwing an exception in a
destructor, unless caught within the destructor, is considered a bad
practice for this very reason.)
This PR modifies disconnect_receiver() to check for the existence of the
entry in the map and bypass the access if it is not present, thus
preventing the exception from being thrown in this function which is
invoked from another object's destructor.
-rw-r--r-- | host/lib/transport/inline_io_service.cpp | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/host/lib/transport/inline_io_service.cpp b/host/lib/transport/inline_io_service.cpp index 7eb3072b7..631ee1bc3 100644 --- a/host/lib/transport/inline_io_service.cpp +++ b/host/lib/transport/inline_io_service.cpp @@ -444,17 +444,17 @@ void inline_io_service::connect_receiver( void inline_io_service::disconnect_receiver(recv_link_if* link, inline_recv_cb* cb) { - inline_recv_mux* mux; - inline_recv_cb* rcvr; - std::tie(mux, rcvr) = _recv_tbl.at(link); - if (mux) { - mux->disconnect(cb); - if (mux->is_empty()) { - delete mux; - mux = nullptr; + inline_recv_mux* mux = nullptr; + inline_recv_cb* rcvr = nullptr; + if (_recv_tbl.count(link)) { + std::tie(mux, rcvr) = _recv_tbl.at(link); + if (mux) { + mux->disconnect(cb); + if (mux->is_empty()) { + delete mux; + mux = nullptr; + } } - } else { - rcvr = nullptr; } _recv_tbl[link] = std::make_tuple(mux, rcvr); } |