OSDN Git Service

Some code refactoring in the "startup" threads.
[x264-launcher/x264-launcher.git] / src / thread_startup.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Simple x264 Launcher
3 // Copyright (C) 2004-2019 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
21
22 #include "thread_startup.h"
23
24 //MUtils
25 #include <MUtils/Global.h>
26
27 //Qt
28 #include <QDir>
29 #include <QElapsedTimer>
30 #include <QProcess>
31
32 //-------------------------------------
33 // Constructor
34 //-------------------------------------
35
36 StarupThread::StarupThread(void)
37 {
38         m_exception = false;
39         m_success = 0;
40 }
41
42 StarupThread::~StarupThread(void)
43 {
44 }
45
46 //-------------------------------------
47 // Thread entry point
48 //-------------------------------------
49
50 void StarupThread::run(void)
51 {
52         m_exception = false;
53         m_success = 0;
54         runChecked1(this, m_success, &m_exception);
55 }
56
57 void StarupThread::runChecked1(StarupThread *const thread, volatile int &success, volatile bool *exception)
58 {
59         __try
60         {
61                 return runChecked2(thread, success, exception);
62         }
63         __except(1)
64         {
65                 *exception = true;
66                 qWarning("Unhandled exception error in startup thread !!!");
67         }
68 }
69
70 void StarupThread::runChecked2(StarupThread *const thread, volatile int &success, volatile bool *exception)
71 {
72         try
73         {
74                 success = thread->threadMain();
75         }
76         catch(...)
77         {
78                 *exception = true;
79                 qWarning("Startup thread raised an C++ exception!");
80         }
81 }
82
83 //-------------------------------------
84 // Utility functions
85 //-------------------------------------
86
87 QStringList StarupThread::runProcess(const QString &exePath, const QStringList &arguments, const QStringList *const extraPaths)
88 {
89         QProcess process;
90
91         //Get file name
92         const QString fileName = QFileInfo(exePath).fileName().toUpper();
93
94         //Setup process object
95         MUtils::init_process(process, QDir::tempPath(), true, extraPaths);
96
97         //Try to start process
98         process.start(exePath, arguments);
99         if (!process.waitForStarted())
100         {
101                 qWarning("Failed to launch %s -> %s", MUTILS_UTF8(fileName), MUTILS_UTF8(process.errorString()));
102                 return QStringList();
103         }
104
105         //Start the timer
106         QElapsedTimer timer;
107         timer.start();
108
109         //Wait until process has finished
110         QStringList processOutput;
111         while (process.state() != QProcess::NotRunning)
112         {
113                 process.waitForReadyRead(1250);
114                 while (process.canReadLine())
115                 {
116                         const QString line = QString::fromUtf8(process.readLine()).simplified();
117                         if (!line.isEmpty())
118                         {
119                                 processOutput << line;
120                         }
121                 }
122                 if ((process.state() != QProcess::NotRunning) && timer.hasExpired(15000))
123                 {
124                         process.waitForFinished(125);
125                         if (process.state() != QProcess::NotRunning)
126                         {
127                                 qWarning("%s process encountered a deadlock -> aborting now!", MUTILS_UTF8(fileName));
128                                 break;
129                         }
130                 }
131                 else
132                 {
133                         QThread::yieldCurrentThread(); /*yield*/
134                 }
135         }
136
137         //Make sure process has terminated!
138         process.waitForFinished(1250);
139         if (process.state() != QProcess::NotRunning)
140         {
141                 qWarning("%s process still running, going to kill it!", MUTILS_UTF8(fileName));
142                 process.kill();
143                 process.waitForFinished(-1);
144         }
145
146         //Read pending lines
147         while (process.bytesAvailable() > 0)
148         {
149                 const QString line = QString::fromUtf8(process.readLine()).simplified();
150                 if (!line.isEmpty())
151                 {
152                         processOutput << line;
153                 }
154         }
155
156         //Check exit code
157         if (process.exitCode() != 0)
158         {
159                 qWarning("%s failed with code 0x%08X -> discarding all output!", MUTILS_UTF8(fileName), process.exitCode());
160                 return QStringList();
161         }
162
163         return processOutput;
164 }