Ensure no ubuntu-server process is running at startup. Fixes #6584
Signed-off-by: Pedro Pombeiro <pombeirp@users.noreply.github.com>
This commit is contained in:
parent
73ccb44663
commit
50200404ce
|
@ -130,6 +130,7 @@ CMakeCache.txt
|
||||||
**/CMakeFiles/
|
**/CMakeFiles/
|
||||||
/StatusImPackage/*
|
/StatusImPackage/*
|
||||||
*.AppImage
|
*.AppImage
|
||||||
|
Status-Windows-x86_64.zip
|
||||||
/desktop/bin/*
|
/desktop/bin/*
|
||||||
/desktop/lib/*
|
/desktop/lib/*
|
||||||
/desktop/modules/*
|
/desktop/modules/*
|
||||||
|
|
150
desktop/main.cpp
150
desktop/main.cpp
|
@ -38,8 +38,9 @@ static QStringList consoleOutputStrings;
|
||||||
static QMutex consoleOutputMutex;
|
static QMutex consoleOutputMutex;
|
||||||
|
|
||||||
#ifdef BUILD_FOR_BUNDLE
|
#ifdef BUILD_FOR_BUNDLE
|
||||||
bool ubuntuServerStarted = false;
|
bool nodeJsServerStarted = false;
|
||||||
QProcess *g_ubuntuServerProcess = nullptr;
|
QProcess *g_nodeJsServerProcess = nullptr;
|
||||||
|
#define NODEJS_SERVER_NAME "ubuntu-server"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const int MAIN_WINDOW_WIDTH = 1024;
|
const int MAIN_WINDOW_WIDTH = 1024;
|
||||||
|
@ -54,12 +55,12 @@ const char *LOG_FILE_PATH_ENV_VAR_NAME = "STATUS_LOG_PATH";
|
||||||
// TODO: some way to change while running
|
// TODO: some way to change while running
|
||||||
class ReactNativeProperties : public QObject {
|
class ReactNativeProperties : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool liveReload READ liveReload WRITE setLiveReload NOTIFY
|
Q_PROPERTY(
|
||||||
liveReloadChanged)
|
bool liveReload READ liveReload WRITE setLiveReload NOTIFY liveReloadChanged)
|
||||||
Q_PROPERTY(QUrl codeLocation READ codeLocation WRITE setCodeLocation NOTIFY
|
Q_PROPERTY(
|
||||||
codeLocationChanged)
|
QUrl codeLocation READ codeLocation WRITE setCodeLocation NOTIFY codeLocationChanged)
|
||||||
Q_PROPERTY(QString pluginsPath READ pluginsPath WRITE setPluginsPath NOTIFY
|
Q_PROPERTY(
|
||||||
pluginsPathChanged)
|
QString pluginsPath READ pluginsPath WRITE setPluginsPath NOTIFY pluginsPathChanged)
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
QString executor READ executor WRITE setExecutor NOTIFY executorChanged)
|
QString executor READ executor WRITE setExecutor NOTIFY executorChanged)
|
||||||
public:
|
public:
|
||||||
|
@ -155,26 +156,29 @@ void writeSingleLineLogFromJSServer(const QString &msg);
|
||||||
|
|
||||||
#ifdef BUILD_FOR_BUNDLE
|
#ifdef BUILD_FOR_BUNDLE
|
||||||
|
|
||||||
void runUbuntuServer();
|
void killZombieJsServer();
|
||||||
|
bool runNodeJsServer();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void loadFontsFromResources() {
|
void loadFontsFromResources() {
|
||||||
|
|
||||||
QDirIterator it(":", QDirIterator::Subdirectories);
|
QDirIterator it(":", QDirIterator::Subdirectories);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
QString resourceFile = it.next();
|
QString resourceFile = it.next();
|
||||||
if (resourceFile.endsWith(".otf", Qt::CaseInsensitive) ||
|
if (resourceFile.endsWith(".otf", Qt::CaseInsensitive) ||
|
||||||
resourceFile.endsWith(".ttf", Qt::CaseInsensitive)) {
|
resourceFile.endsWith(".ttf", Qt::CaseInsensitive)) {
|
||||||
QFontDatabase::addApplicationFont(resourceFile);
|
qint32 fontId = QFontDatabase::addApplicationFont(resourceFile);
|
||||||
|
if (Q_UNLIKELY(fontId == -1)) {
|
||||||
|
qCDebug(STATUS) << "Unable to install font" << resourceFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void exceptionPostHandledCallback() {
|
void exceptionPostHandledCallback() {
|
||||||
#ifdef BUILD_FOR_BUNDLE
|
#ifdef BUILD_FOR_BUNDLE
|
||||||
if (g_ubuntuServerProcess) {
|
if (g_nodeJsServerProcess) {
|
||||||
g_ubuntuServerProcess->kill();
|
g_nodeJsServerProcess->kill();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -199,7 +203,6 @@ QString getDataStoragePath() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
|
@ -207,7 +210,9 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
QString appPath = QCoreApplication::applicationDirPath();
|
QString appPath = QCoreApplication::applicationDirPath();
|
||||||
QString dataStoragePath = getDataStoragePath();
|
QString dataStoragePath = getDataStoragePath();
|
||||||
#ifndef BUILD_FOR_BUNDLE
|
#ifdef BUILD_FOR_BUNDLE
|
||||||
|
killZombieJsServer();
|
||||||
|
#else
|
||||||
appPath.append(CRASH_REPORT_EXECUTABLE_RELATIVE_PATH);
|
appPath.append(CRASH_REPORT_EXECUTABLE_RELATIVE_PATH);
|
||||||
dataStoragePath = "";
|
dataStoragePath = "";
|
||||||
#endif
|
#endif
|
||||||
|
@ -227,7 +232,15 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BUILD_FOR_BUNDLE
|
#ifdef BUILD_FOR_BUNDLE
|
||||||
runUbuntuServer();
|
if (!runNodeJsServer()) {
|
||||||
|
if (g_nodeJsServerProcess->state() == QProcess::NotRunning) {
|
||||||
|
// If we failed to start the Node.js server (happens on Windows if the Node.js server process was previously running), let's do a final attempt
|
||||||
|
delete g_nodeJsServerProcess;
|
||||||
|
if (!runNodeJsServer()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
app.setWindowIcon(QIcon(":/icon.png"));
|
app.setWindowIcon(QIcon(":/icon.png"));
|
||||||
#endif
|
#endif
|
||||||
|
@ -285,11 +298,11 @@ int main(int argc, char **argv) {
|
||||||
QString getLogFilePath() {
|
QString getLogFilePath() {
|
||||||
QString logFilePath;
|
QString logFilePath;
|
||||||
#ifdef BUILD_FOR_BUNDLE
|
#ifdef BUILD_FOR_BUNDLE
|
||||||
logFilePath = getDataStoragePath() + "/Status.log";
|
logFilePath = getDataStoragePath() + QDir::separator() + "Status.log";
|
||||||
#else
|
#else
|
||||||
logFilePath = qEnvironmentVariable(LOG_FILE_PATH_ENV_VAR_NAME, "");
|
logFilePath = qEnvironmentVariable(LOG_FILE_PATH_ENV_VAR_NAME, "");
|
||||||
if (logFilePath.isEmpty()) {
|
if (logFilePath.isEmpty()) {
|
||||||
logFilePath = getDataStoragePath() + "/StatusDev.log";
|
logFilePath = getDataStoragePath() + QDir::separator() + "StatusDev.log";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return logFilePath;
|
return logFilePath;
|
||||||
|
@ -310,49 +323,112 @@ void writeLogsToFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BUILD_FOR_BUNDLE
|
#ifdef BUILD_FOR_BUNDLE
|
||||||
void runUbuntuServer() {
|
|
||||||
g_ubuntuServerProcess = new QProcess();
|
#ifdef Q_OS_WIN
|
||||||
g_ubuntuServerProcess->setWorkingDirectory(getDataStoragePath());
|
|
||||||
g_ubuntuServerProcess->setProgram(QGuiApplication::applicationDirPath() +
|
#include <windows.h>
|
||||||
"/ubuntu-server");
|
#include <tlhelp32.h>
|
||||||
QObject::connect(g_ubuntuServerProcess, &QProcess::errorOccurred,
|
|
||||||
|
bool IsProcessRunning(const wchar_t *processName) {
|
||||||
|
bool exists = false;
|
||||||
|
PROCESSENTRY32 entry = { sizeof(PROCESSENTRY32) };
|
||||||
|
|
||||||
|
HANDLE snapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
|
if (snapshot != NULL) {
|
||||||
|
if (::Process32First(snapshot, &entry)) {
|
||||||
|
do {
|
||||||
|
if (!wcsicmp(entry.szExeFile, processName)) {
|
||||||
|
exists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (::Process32Next(snapshot, &entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
::CloseHandle(snapshot);
|
||||||
|
}
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void killZombieJsServer() {
|
||||||
|
// Ensure that a zombie Node.js server process is not still running in the background before we spawn a new one
|
||||||
|
QString cmd;
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
cmd = QString("pkill -f %1").arg(NODEJS_SERVER_NAME);
|
||||||
|
#elif defined(Q_OS_MAC)
|
||||||
|
cmd = QString("killall -9 %1").arg(NODEJS_SERVER_NAME);
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
#define _CAT(A, B) A##B
|
||||||
|
#define _W(A) _CAT(L, #A)
|
||||||
|
WCHAR exeName[_MAX_PATH];
|
||||||
|
wsprintf(exeName, L"%s.exe", _W(NODEJS_SERVER_NAME));
|
||||||
|
if (IsProcessRunning(exeName)) {
|
||||||
|
qCDebug(STATUS) << NODEJS_SERVER_NAME << "is running, killing it";
|
||||||
|
::ShellExecuteW(NULL, NULL, L"tskill", _W(NODEJS_SERVER_NAME), NULL, SW_HIDE);
|
||||||
|
} else {
|
||||||
|
qCDebug(STATUS) << NODEJS_SERVER_NAME << "is not running";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!cmd.isEmpty()) {
|
||||||
|
qCDebug(STATUS) << "Running " << cmd;
|
||||||
|
QByteArray cmdArray = cmd.toLocal8Bit();
|
||||||
|
system(cmdArray.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool runNodeJsServer() {
|
||||||
|
g_nodeJsServerProcess = new QProcess();
|
||||||
|
g_nodeJsServerProcess->setWorkingDirectory(getDataStoragePath());
|
||||||
|
g_nodeJsServerProcess->setProgram(QGuiApplication::applicationDirPath() + QDir::separator() + NODEJS_SERVER_NAME);
|
||||||
|
QObject::connect(g_nodeJsServerProcess, &QProcess::errorOccurred,
|
||||||
[=](QProcess::ProcessError) {
|
[=](QProcess::ProcessError) {
|
||||||
qCWarning(JSSERVER) << "process name: "
|
qCWarning(JSSERVER) << "process name: "
|
||||||
<< qUtf8Printable(g_ubuntuServerProcess->program());
|
<< qUtf8Printable(g_nodeJsServerProcess->program());
|
||||||
qCWarning(JSSERVER) << "process error: "
|
qCWarning(JSSERVER) << "process error: "
|
||||||
<< qUtf8Printable(g_ubuntuServerProcess->errorString());
|
<< qUtf8Printable(g_nodeJsServerProcess->errorString());
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
g_ubuntuServerProcess, &QProcess::readyReadStandardOutput, [=] {
|
g_nodeJsServerProcess, &QProcess::readyReadStandardOutput, [=] {
|
||||||
writeLogFromJSServer(g_ubuntuServerProcess->readAllStandardOutput().trimmed());
|
writeLogFromJSServer(g_nodeJsServerProcess->readAllStandardOutput().trimmed());
|
||||||
});
|
});
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
g_ubuntuServerProcess, &QProcess::readyReadStandardError, [=] {
|
g_nodeJsServerProcess, &QProcess::readyReadStandardError, [=] {
|
||||||
QString output =
|
QString output =
|
||||||
g_ubuntuServerProcess->readAllStandardError().trimmed();
|
g_nodeJsServerProcess->readAllStandardError().trimmed();
|
||||||
writeLogFromJSServer(output);
|
writeLogFromJSServer(output);
|
||||||
if (output.contains("Server starting")) {
|
if (output.contains("Server starting")) {
|
||||||
ubuntuServerStarted = true;
|
nodeJsServerStarted = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(QGuiApplication::instance(), &QCoreApplication::aboutToQuit,
|
QObject::connect(QGuiApplication::instance(), &QCoreApplication::aboutToQuit,
|
||||||
[=]() {
|
[=]() {
|
||||||
qCDebug(STATUS) << "Kill ubuntu server";
|
qCDebug(STATUS) << "Kill node.js server process";
|
||||||
g_ubuntuServerProcess->kill();
|
g_nodeJsServerProcess->kill();
|
||||||
});
|
});
|
||||||
|
|
||||||
qCDebug(STATUS) << "starting ubuntu server...";
|
qCDebug(STATUS) << "starting node.js server process...";
|
||||||
g_ubuntuServerProcess->start();
|
g_nodeJsServerProcess->start();
|
||||||
qCDebug(STATUS) << "wait for started...";
|
qCDebug(STATUS) << "wait for started...";
|
||||||
|
|
||||||
while (!ubuntuServerStarted) {
|
if (g_nodeJsServerProcess->waitForReadyRead(10000)) {
|
||||||
|
// We know that the process started, now wait until it communicates that it has started
|
||||||
|
while (!nodeJsServerStarted) {
|
||||||
QGuiApplication::processEvents();
|
QGuiApplication::processEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(STATUS) << "waiting finished";
|
qCDebug(STATUS) << "waiting finished";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
qCDebug(STATUS) << "failed to start process";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void writeLogFromJSServer(const QString &msg) {
|
void writeLogFromJSServer(const QString &msg) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Build
|
# Build
|
||||||
|
|
||||||
```
|
``` shell
|
||||||
docker-compose -f docker-build/docker-compose.yml build
|
docker-compose -f docker-build/docker-compose.yml build
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ This will install all the required sdks, depending on the connection will take s
|
||||||
|
|
||||||
# Run
|
# Run
|
||||||
|
|
||||||
```
|
``` shell
|
||||||
docker-compose -f docker-build/docker-compose.yml up
|
docker-compose -f docker-build/docker-compose.yml up
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ You need to connect your device and accept the key.
|
||||||
|
|
||||||
After the figwheel prompt you can install the application running:
|
After the figwheel prompt you can install the application running:
|
||||||
|
|
||||||
```
|
``` shell
|
||||||
docker-compose -f docker-build/docker-compose.yml exec adbd make run-android
|
docker-compose -f docker-build/docker-compose.yml exec adbd make run-android
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -207,11 +207,12 @@ function compile() {
|
||||||
-DJS_BUNDLE_PATH="$JS_BUNDLE_PATH" \
|
-DJS_BUNDLE_PATH="$JS_BUNDLE_PATH" \
|
||||||
-DCMAKE_CXX_FLAGS:='-DBUILD_FOR_BUNDLE=1' || exit 1
|
-DCMAKE_CXX_FLAGS:='-DBUILD_FOR_BUNDLE=1' || exit 1
|
||||||
fi
|
fi
|
||||||
make -j5 || exit 1
|
make -S -j5 || exit 1
|
||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
function bundleWindows() {
|
function bundleWindows() {
|
||||||
|
local buildType="$1"
|
||||||
# TODO: Produce a setup program instead of a ZIP
|
# TODO: Produce a setup program instead of a ZIP
|
||||||
pushd $WORKFOLDER
|
pushd $WORKFOLDER
|
||||||
rm -rf Windows
|
rm -rf Windows
|
||||||
|
@ -227,9 +228,10 @@ function bundleWindows() {
|
||||||
pushd Windows
|
pushd Windows
|
||||||
cp $STATUSREACTPATH/.env .
|
cp $STATUSREACTPATH/.env .
|
||||||
mkdir -p assets/resources notifier
|
mkdir -p assets/resources notifier
|
||||||
cp $STATUSREACTPATH/node_modules/node-notifier/vendor/snoreToast/SnoreToast.exe \
|
cp $STATUSREACTPATH/node_modules/node-notifier/vendor/notifu/*.exe \
|
||||||
$STATUSREACTPATH/node_modules/node-notifier/vendor/notifu/*.exe \
|
|
||||||
notifier/
|
notifier/
|
||||||
|
cp $STATUSREACTPATH/node_modules/node-notifier/vendor/snoreToast/SnoreToast.exe \
|
||||||
|
.
|
||||||
cp -r $STATUSREACTPATH/resources/fonts \
|
cp -r $STATUSREACTPATH/resources/fonts \
|
||||||
$STATUSREACTPATH/resources/icons \
|
$STATUSREACTPATH/resources/icons \
|
||||||
$STATUSREACTPATH/resources/images \
|
$STATUSREACTPATH/resources/images \
|
||||||
|
@ -237,7 +239,14 @@ function bundleWindows() {
|
||||||
local _bin=$STATUSREACTPATH/desktop/bin
|
local _bin=$STATUSREACTPATH/desktop/bin
|
||||||
rm -rf $_bin/cmake_install.cmake $_bin/Makefile $_bin/CMakeFiles $_bin/Status_autogen && \
|
rm -rf $_bin/cmake_install.cmake $_bin/Makefile $_bin/CMakeFiles $_bin/Status_autogen && \
|
||||||
cp -r $_bin/* .
|
cp -r $_bin/* .
|
||||||
zip -mr9 ../../Status-Windows-x86_64.zip .
|
|
||||||
|
local zipOptions="-mr9"
|
||||||
|
if [ -z $buildType ]; then
|
||||||
|
zipOptions="-mr1"
|
||||||
|
elif [ "$buildType" = "pr" ]; then
|
||||||
|
zipOptions="-mr2"
|
||||||
|
fi
|
||||||
|
zip $zipOptions ../../Status-Windows-x86_64.zip .
|
||||||
popd
|
popd
|
||||||
rm -rf Windows
|
rm -rf Windows
|
||||||
popd
|
popd
|
||||||
|
|
Loading…
Reference in New Issue