MythTV  master
mythsystem.cpp
Go to the documentation of this file.
1 /* -*- Mode: c++ -*-
2  * Class MythSystem
3  *
4  * Copyright (C) Daniel Kristjansson 2013
5  * Copyright (C) Gavin Hurlbut 2012
6  * Copyright (C) Issac Richards 2008
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 // C++ headers
24 #include <cstdint>
25 #include <csignal> // for SIGXXX
26 
27 // Qt headers
28 #include <QByteArray>
29 #include <QIODevice>
30 #include <QRegExp>
31 #include <QStringList>
32 #include <utility>
33 
34 // MythTV headers
35 #include "mythsystemlegacy.h"
36 #include "mythsystem.h"
37 #include "exitcodes.h"
38 
39 using namespace std;
40 
42 {
43  public:
45  const QStringList &args,
46  uint flags,
47  const QString& startPath,
48  Priority /*cpuPriority*/,
49  Priority /*diskPriority*/)
50  {
51  if (args.empty())
52  return nullptr;
53 
54  auto *legacy = new MythSystemLegacy(args.join(" "), flags);
55 
56  if (!startPath.isEmpty())
57  legacy->SetDirectory(startPath);
58 
60  if ((ac & flags) == ac)
61  {
62  legacy->Run();
63  return nullptr;
64  }
65 
66  auto *wrapper = new MythSystemLegacyWrapper(legacy, flags);
67 
68  // TODO implement cpuPriority and diskPriority
69  return wrapper;
70  }
71 
72  ~MythSystemLegacyWrapper(void) override
73  {
75  }
76 
77  uint GetFlags(void) const override // MythSystem
78  {
79  return m_flags;
80  }
81 
83  QString GetStartingPath(void) const override // MythSystem
84  {
85  return m_legacy->GetDirectory();
86  }
87 
89  Priority GetCPUPriority(void) const override // MythSystem
90  {
91  return kNormalPriority;
92  }
93 
95  Priority GetDiskPriority(void) const override // MythSystem
96  {
97  return kNormalPriority;
98  }
99 
106  bool Wait(uint timeout_ms) override // MythSystem
107  {
108  timeout_ms = (timeout_ms >= 1000) ? timeout_ms + 500 :
109  ((timeout_ms == 0) ? 0 : 1000);
110  uint legacy_wait_ret = m_legacy->Wait(timeout_ms / 1000);
111  return GENERIC_EXIT_RUNNING != legacy_wait_ret;
112  }
113 
117  QIODevice *GetStandardInputStream(void) override // MythSystem
118  {
119  if (!(kMSStdIn & m_flags))
120  return nullptr;
121 
122  if (!m_legacy->GetBuffer(0)->isOpen() &&
123  !m_legacy->GetBuffer(0)->open(QIODevice::WriteOnly))
124  {
125  return nullptr;
126  }
127 
128  return m_legacy->GetBuffer(0);
129  }
130 
133  QIODevice *GetStandardOutputStream(void) override // MythSystem
134  {
135  if (!(kMSStdOut & m_flags))
136  return nullptr;
137 
138  Wait(0); // legacy getbuffer is not thread-safe, so wait
139 
140  if (!m_legacy->GetBuffer(1)->isOpen() &&
141  !m_legacy->GetBuffer(1)->open(QIODevice::ReadOnly))
142  {
143  return nullptr;
144  }
145 
146  return m_legacy->GetBuffer(1);
147  }
148 
151  QIODevice *GetStandardErrorStream(void) override // MythSystem
152  {
153  if (!(kMSStdErr & m_flags))
154  return nullptr;
155 
156  Wait(0); // legacy getbuffer is not thread-safe, so wait
157 
158  if (!m_legacy->GetBuffer(2)->isOpen() &&
159  !m_legacy->GetBuffer(2)->open(QIODevice::ReadOnly))
160  {
161  return nullptr;
162  }
163 
164  return m_legacy->GetBuffer(2);
165  }
166 
168  void Signal(MythSignal sig) override // MythSystem
169  {
170  m_legacy->Signal(sig);
171  }
172 
179  int GetExitCode(void) const override // MythSystem
180  {
181  // FIXME doesn't actually know why program exited.
182  // if program returns 142 then we will forever
183  // think it is running even though it is not.
184  int status = m_legacy->GetStatus();
185  if (GENERIC_EXIT_RUNNING == status)
186  return -2;
187  if (GENERIC_EXIT_KILLED == status)
188  return -1;
189  return status;
190  }
191 
192  private:
194  m_legacy(legacy), m_flags(flags)
195  {
196  m_legacy->Run();
197  }
198 
199  private:
200  QScopedPointer<MythSystemLegacy> m_legacy;
202 };
203 
205  const QStringList &args,
206  uint flags,
207  const QString& startPath,
208  Priority cpuPriority,
209  Priority diskPriority)
210 {
212  args, flags, startPath, cpuPriority, diskPriority);
213 }
214 
216  const QString& args,
217  uint flags,
218  const QString& startPath,
219  Priority cpuPriority,
220  Priority diskPriority)
221 {
222  return MythSystem::Create(
223  args.split(QRegExp("\\s+")), flags, startPath,
224  cpuPriority, diskPriority);
225 }
Priority GetDiskPriority(void) const override
Return the Disk Priority of the program.
Definition: mythsystem.cpp:95
Priority GetCPUPriority(void) const override
Return the CPU Priority of the program.
Definition: mythsystem.cpp:89
#define GENERIC_EXIT_KILLED
Process killed or stopped.
Definition: exitcodes.h:23
int GetExitCode(void) const override
returns the exit code, if any, that the program returned.
Definition: mythsystem.cpp:179
QString GetStartingPath(void) const override
Returns the starting path of the program.
Definition: mythsystem.cpp:83
uint GetFlags(void) const override
Returns the flags passed to the constructor.
Definition: mythsystem.cpp:77
QIODevice * GetStandardOutputStream(void) override
Returns the standard output stream for the program if the kMSStdOut flag was passed to the constructo...
Definition: mythsystem.cpp:133
QScopedPointer< MythSystemLegacy > m_legacy
Definition: mythsystem.cpp:200
void SetDirectory(const QString &)
static MythSystem * Create(const QStringList &args, uint flags=kMSNone, const QString &startPath=QString(), Priority cpuPriority=kInheritPriority, Priority diskPriority=kInheritPriority)
Definition: mythsystem.cpp:204
#define GENERIC_EXIT_RUNNING
Process is running.
Definition: exitcodes.h:25
unsigned int uint
Definition: compat.h:140
class for managing sub-processes.
Definition: mythsystem.h:81
automatically delete if backgrounded
Definition: mythsystem.h:43
static MythSystemLegacyWrapper * Create(const QStringList &args, uint flags, const QString &startPath, Priority, Priority)
Definition: mythsystem.cpp:44
MythSystemLegacyWrapper(MythSystemLegacy *legacy, uint flags)
Definition: mythsystem.cpp:193
run child in the background
Definition: mythsystem.h:36
MythSignal
Definition: mythsystem.h:54
void Signal(MythSignal sig) override
Sends the selected signal to the program.
Definition: mythsystem.cpp:168
QIODevice * GetStandardInputStream(void) override
Returns the standard input stream for the program if the kMSStdIn flag was passed to the constructor.
Definition: mythsystem.cpp:117
bool Wait(uint timeout_ms) override
Blocks until child process is collected or timeout reached.
Definition: mythsystem.cpp:106
~MythSystemLegacyWrapper(void) override
Definition: mythsystem.cpp:72
allow access to stdin
Definition: mythsystem.h:38
allow access to stderr
Definition: mythsystem.h:40
QIODevice * GetStandardErrorStream(void) override
Returns the standard error stream for the program if the kMSStdErr flag was passed to the constructor...
Definition: mythsystem.cpp:151
allow access to stdout
Definition: mythsystem.h:39