mirror of
https://github.com/debauchee/barrier.git
synced 2024-12-24 11:32:43 +03:00
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:
parent
d8237238b4
commit
d9530bf7aa
@ -32,6 +32,7 @@
|
|||||||
#include "QUtility.h"
|
#include "QUtility.h"
|
||||||
#include "ProcessorArch.h"
|
#include "ProcessorArch.h"
|
||||||
#include "SslCertificate.h"
|
#include "SslCertificate.h"
|
||||||
|
#include "ShutdownCh.h"
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
@ -773,6 +774,9 @@ void MainWindow::stopDesktop()
|
|||||||
appendLogInfo("stopping barrier desktop process");
|
appendLogInfo("stopping barrier desktop process");
|
||||||
|
|
||||||
if (barrierProcess()->isOpen()) {
|
if (barrierProcess()->isOpen()) {
|
||||||
|
// try to shutdown child gracefully
|
||||||
|
barrierProcess()->write(&ShutdownCh, 1);
|
||||||
|
barrierProcess()->waitForFinished(5000);
|
||||||
barrierProcess()->close();
|
barrierProcess()->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
22
src/gui/src/ShutdownCh.h
Normal file
22
src/gui/src/ShutdownCh.h
Normal 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';
|
||||||
|
|
@ -27,6 +27,7 @@
|
|||||||
#include "base/EventTypes.h"
|
#include "base/EventTypes.h"
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
#include "base/XBase.h"
|
#include "base/XBase.h"
|
||||||
|
#include "../gui/src/ShutdownCh.h"
|
||||||
|
|
||||||
EVENT_TYPE_ACCESSOR(Client)
|
EVENT_TYPE_ACCESSOR(Client)
|
||||||
EVENT_TYPE_ACCESSOR(IStream)
|
EVENT_TYPE_ACCESSOR(IStream)
|
||||||
@ -205,6 +206,12 @@ EventQueue::getEvent(Event& event, double timeout)
|
|||||||
{
|
{
|
||||||
Stopwatch timer(true);
|
Stopwatch timer(true);
|
||||||
retry:
|
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
|
// if no events are waiting then handle timers and then wait
|
||||||
while (m_buffer->isEmpty()) {
|
while (m_buffer->isEmpty()) {
|
||||||
// handle timers first
|
// handle timers first
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "base/Stopwatch.h"
|
#include "base/Stopwatch.h"
|
||||||
#include "common/stdmap.h"
|
#include "common/stdmap.h"
|
||||||
#include "common/stdset.h"
|
#include "common/stdset.h"
|
||||||
|
#include "base/NonBlockingStream.h"
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
@ -184,6 +185,7 @@ private:
|
|||||||
Mutex* m_readyMutex;
|
Mutex* m_readyMutex;
|
||||||
CondVar<bool>* m_readyCondVar;
|
CondVar<bool>* m_readyCondVar;
|
||||||
std::queue<Event> m_pending;
|
std::queue<Event> m_pending;
|
||||||
|
NonBlockingStream m_parentStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EVENT_TYPE_ACCESSOR(type_) \
|
#define EVENT_TYPE_ACCESSOR(type_) \
|
||||||
|
56
src/lib/base/NonBlockingStream.cpp
Normal file
56
src/lib/base/NonBlockingStream.cpp
Normal 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;
|
||||||
|
}
|
34
src/lib/base/NonBlockingStream.h
Normal file
34
src/lib/base/NonBlockingStream.h
Normal 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;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user