diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index abf556ed..dc6a1c17 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -40,6 +40,13 @@ The full set of tests is only run for tagged releases. - renamed kw11p tbench from w11a_kw11p to kw11p ### Bug Fixes +- ReventLoop: fixed a design error in the `RemovePollHandler` flow, which + allowed that `DoPoll` returned while poll list updates were still pending + and the subsequent execution of `DoCall` called removed handlers. This + lead to `SIGSEGV` crashes when a `detach` command was executed for a + a `tcp` type virtual terminal or a `tap` type virtual ethernet device, see + [issue #14](https://github.com/wfjm/w11/issues/14). + ### Known issues diff --git a/tools/src/librlink/ReventLoop.cpp b/tools/src/librlink/ReventLoop.cpp index 9d2a8822..5482bd4f 100644 --- a/tools/src/librlink/ReventLoop.cpp +++ b/tools/src/librlink/ReventLoop.cpp @@ -1,6 +1,6 @@ -// $Id: ReventLoop.cpp 1090 2018-12-21 12:17:35Z mueller $ +// $Id: ReventLoop.cpp 1150 2019-05-19 17:52:54Z mueller $ // -// Copyright 2013-2018 by Walter F.J. Mueller +// Copyright 2013-2019 by Walter F.J. Mueller // // This program is free software; you may redistribute and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -13,6 +13,7 @@ // // Revision History: // Date Rev Version Comment +// 2019-05-17 1150 1.3 BUGFIX: don't call handler when fUpdatePoll true // 2018-12-19 1090 1.2.6 use RosPrintf(bool) // 2018-12-18 1089 1.2.5 use c++ style casts // 2018-12-17 1085 1.2.4 use std::lock_guard instead of boost @@ -218,42 +219,46 @@ void ReventLoop::Dump(std::ostream& os, int ind, const char* text, int ReventLoop::DoPoll(int timeout) { - if (fUpdatePoll) { - lock_guard lock(fPollDscMutex); + int irc = 0; + do { + if (fUpdatePoll) { + lock_guard lock(fPollDscMutex); - fPollFd.resize(fPollDsc.size()); - fPollHdl.resize(fPollDsc.size()); - for (size_t i=0; i= 1) { + RlogMsg lmsg(*fspLog, 'I'); + lmsg << "eloop: redo pollfd list, size=" << fPollDsc.size() << endl; + } } - fUpdatePoll = false; - - if (fspLog && fTraceLevel >= 1) { - RlogMsg lmsg(*fspLog, 'I'); - lmsg << "eloop: redo pollfd list, size=" << fPollDsc.size() << endl; - } - } - if (fPollFd.size() == 0) return 0; + if (fPollFd.size() == 0) return 0; + irc = poll(fPollFd.data(), fPollFd.size(), timeout); + if (irc < 0 && errno == EINTR) return 0; + if (irc < 0) + throw Rexception("ReventLoop::EventLoop()", "poll() failed: ", errno); - int irc = poll(fPollFd.data(), fPollFd.size(), timeout); - if (irc < 0 && errno == EINTR) return 0; - if (irc < 0) - throw Rexception("ReventLoop::EventLoop()", "poll() failed: ", errno); - - if (fspLog && fTraceLevel >= 2) { - RlogMsg lmsg(*fspLog, 'I'); - lmsg << "eloop: poll(): rc=" << irc; - for (size_t i=0; i= 2) { + RlogMsg lmsg(*fspLog, 'I'); + lmsg << "eloop: poll(): rc=" << irc; + for (size_t i=0; i= 1) { RlogMsg lmsg(*fspLog, 'I');