/***************************************************************************** * smsub Server Manager Subprocess * Copyright (C) 2020-2021 Syping * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * This software is provided as-is, no warranties are given to you, we are not * responsible for anything with use of the software, you are self responsible. *****************************************************************************/ #include #include #include "SMSubProcess.h" #include "smsub.h" #include SMSubProcess::SMSubProcess(const QString &executable, const QStringList &arguments, const QString &workingDirectory, const int &termTimeout) : termTimeout(termTimeout) { // Set process executable, arguments and working directory process.setProgram(executable); process.setArguments(arguments); process.setWorkingDirectory(workingDirectory); // stdout and stderr in same IO stream process.setProcessChannelMode(QProcess::MergedChannels); // Connect process signal handlers QObject::connect(&process, &QProcess::readyRead, this, &SMSubProcess::readyRead); QObject::connect(&process, &QProcess::errorOccurred, this, &SMSubProcess::processError); QObject::connect(&process, QOverload::of(&QProcess::finished), this, [=](int exitCode) { // Exit with the same exit code as the process emit processStopped(); QCoreApplication::exit(exitCode); }); } void SMSubProcess::start() { process.start(QIODevice::ReadWrite); } void SMSubProcess::readyRead() { // Read process output and emit event while (process.canReadLine()) { const QByteArray readData = process.readLine().trimmed(); emit outputWritten(readData + '\n'); } } void SMSubProcess::processError(QProcess::ProcessError error) { // Handle process errors if (likely(error == QProcess::FailedToStart)) { QTextStream(stderr) << "Process failed to start!" << smsub_endl; QCoreApplication::exit(1); } else if (error == QProcess::UnknownError) { QTextStream(stderr) << "Unknown error occurred!" << smsub_endl; QCoreApplication::exit(1); } } void SMSubProcess::aboutToQuit() { // Main process terminated, terminate subprocess with set timeout if (process.state() == QProcess::Running) { process.terminate(); if (!process.waitForFinished(termTimeout)) { QTextStream(stderr) << "Failed to terminate process!" << smsub_endl; } } } void SMSubProcess::killProcess() { // Kill process as requested if (process.state() == QProcess::Running) { process.kill(); } } void SMSubProcess::stopProcess() { // Terminate process as requested if (process.state() == QProcess::Running) { process.terminate(); } } void SMSubProcess::writeInput(const QByteArray &input) { // Write input from Unix/IPC socket to process process.write(input); }