use a relatively small hack to keep barriers/barrierc from crashing on

unixes when they are killed from the GUI with QProcess's close(). the
stdin stream is going completely unused (though the stdout stream is
not) so use stdin to send a shutdown command. this solution avoids all
the nastiness and overhead of using shared memory, mutexes, condvars,
etc. just to communicate "stop" from one process to another
This commit is contained in:
walker0643 2018-01-31 20:20:06 -05:00
parent d8237238b4
commit d9530bf7aa
6 changed files with 125 additions and 0 deletions

View File

@ -32,6 +32,7 @@
#include "QUtility.h"
#include "ProcessorArch.h"
#include "SslCertificate.h"
#include "ShutdownCh.h"
#include <QtCore>
#include <QtGui>
@ -773,6 +774,9 @@ void MainWindow::stopDesktop()
appendLogInfo("stopping barrier desktop process");
if (barrierProcess()->isOpen()) {
// try to shutdown child gracefully
barrierProcess()->write(&ShutdownCh, 1);
barrierProcess()->waitForFinished(5000);
barrierProcess()->close();
}

22
src/gui/src/ShutdownCh.h Normal file
View File

@ -0,0 +1,22 @@
/*
* barrier -- mouse and keyboard sharing utility
* Copyright (C) 2018 Debauchee Open Source Group
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
// included in both the GUI and the child apps (server & client)
const char ShutdownCh = 'S';

View File

@ -27,6 +27,7 @@
#include "base/EventTypes.h"
#include "base/Log.h"
#include "base/XBase.h"
#include "../gui/src/ShutdownCh.h"
EVENT_TYPE_ACCESSOR(Client)
EVENT_TYPE_ACCESSOR(IStream)
@ -205,6 +206,12 @@ EventQueue::getEvent(Event& event, double timeout)
{
Stopwatch timer(true);
retry:
// check to see if parent wants us to shutdown now
char ch;
if (m_parentStream.try_read_char(ch) && ch == ShutdownCh) {
event = Event(Event::kQuit);
return false;
}
// if no events are waiting then handle timers and then wait
while (m_buffer->isEmpty()) {
// handle timers first

View File

@ -26,6 +26,7 @@
#include "base/Stopwatch.h"
#include "common/stdmap.h"
#include "common/stdset.h"
#include "base/NonBlockingStream.h"
#include <queue>
@ -184,6 +185,7 @@ private:
Mutex* m_readyMutex;
CondVar<bool>* m_readyCondVar;
std::queue<Event> m_pending;
NonBlockingStream m_parentStream;
};
#define EVENT_TYPE_ACCESSOR(type_) \

View File

@ -0,0 +1,56 @@
/*
* barrier -- mouse and keyboard sharing utility
* Copyright (C) 2008 Debauchee Open Source Group
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base/NonBlockingStream.h"
#include <unistd.h> // tcgetattr/tcsetattr, read
#include <termios.h> // tcgetattr/tcsetattr
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
NonBlockingStream::NonBlockingStream(int fd) :
_fd(fd)
{
// disable ICANON & ECHO so we don't have to wait for a newline
// before we get data (and to keep it from being echoed back out)
termios ta;
tcgetattr(fd, &ta);
_p_ta_previous = new termios(ta);
ta.c_lflag &= ~(ICANON | ECHO);
tcsetattr(fd, TCSANOW, &ta);
// prevent IO from blocking so we can poll (read())
int _cntl_previous = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, _cntl_previous | O_NONBLOCK);
}
NonBlockingStream::~NonBlockingStream()
{
tcsetattr(_fd, TCSANOW, _p_ta_previous);
fcntl(_fd, F_SETFL, _cntl_previous);
delete _p_ta_previous;
}
bool NonBlockingStream::try_read_char(char &ch)
{
int result = read(_fd, &ch, 1);
if (result == 1)
return true;
assert(result == -1 && (errno == EAGAIN || errno == EWOULDBLOCK));
return false;
}

View File

@ -0,0 +1,34 @@
/*
* barrier -- mouse and keyboard sharing utility
* Copyright (C) 2008 Debauchee Open Source Group
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
struct termios;
class NonBlockingStream
{
public:
explicit NonBlockingStream(int fd = 0);
~NonBlockingStream();
bool try_read_char(char &ch);
private:
int _fd;
termios * _p_ta_previous;
int _cntl_previous;
};