19#include <QCoreApplication>
38 delete fdMap.value((x)); \
78 MThread(QString(
"SystemIOHandler%1").arg(
read ?
"R" :
"W")),
79 m_pWaitLock(), m_pWait(), m_pLock(), m_pMap(
PMap_t()),
89 LOG(VB_GENERAL, LOG_INFO, QString(
"Starting IO manager (%1)")
90 .arg(
m_read ?
"read" :
"write"));
109 bool datafound =
true;
117 PMap_t::iterator i, next;
138 if ( !PeekNamedPipe( h,
nullptr, 0,
nullptr, &lenAvail,
nullptr) )
141 if ( lenAvail > 65536 )
146 if ( !ReadFile( h, &
m_readbuf, lenAvail, &lenRead,
nullptr ) || lenRead == 0 )
152 buff->buffer().append(
m_readbuf, lenRead);
175 int pos = buff->pos();
176 DWORD len = buff->size() - pos;
178 len = (len > 32768 ? 32768 : len);
180 if( !WriteFile(h, buff->read(len).constData(), len, &rlen,
nullptr) )
187 buff->seek(pos+rlen);
203 while (
m_pMap.contains(h))
242 LOG(VB_GENERAL, LOG_INFO,
"Starting process manager");
261 if ( result == WAIT_TIMEOUT || result == WAIT_FAILED )
267 int index = result - WAIT_OBJECT_0;
284 LOG(VB_SYSTEM, LOG_ERR,
285 QString(
"Structure for child handle %1 already deleted!")
286 .arg((
long long)child));
300 GetExitCodeProcess( child, &status );
303 LOG(VB_SYSTEM, LOG_INFO,
304 QString(
"Managed child (Handle: %1) has exited! "
305 "command=%2, status=%3, result=%4")
306 .arg((
long long)child) .arg(ms->
GetLogCmd()) .arg(status)
311 auto now = SystemClock::now();
326 LOG(VB_SYSTEM, LOG_INFO,
327 QString(
"Managed child (Handle: %1) timed out, "
328 "issuing KILL signal").arg((
long long)child));
337 LOG(VB_SYSTEM, LOG_INFO,
338 QString(
"Managed child (Handle: %1) timed out"
339 ", issuing TERM signal").arg((
long long)child));
382 HANDLE *new_children;
387 LOG(VB_SYSTEM, LOG_CRIT,
"No memory to allocate new children");
413 QByteArray ba = ms->
GetBuffer(0)->data();
415 wtb.open(QIODevice::ReadOnly);
457 LOG(VB_GENERAL, LOG_INFO,
"Starting process signal handler");
579 LOG(VB_SYSTEM, LOG_INFO, QString(
"Child Handle %1 killed with %2")
580 .arg((
long long)
m_child).arg(sig));
581 TerminateProcess(
m_child, sig * 256 );
585#define MAX_BUFLEN 1024
588 BOOL bInherit = FALSE;
592 LOG(VB_SYSTEM, LOG_DEBUG, QString(
"Launching: %1").arg(
GetLogCmd()));
594 HANDLE p_stdin[2] = {
nullptr,
nullptr };
595 HANDLE p_stdout[2] = {
nullptr,
nullptr };
596 HANDLE p_stderr[2] = {
nullptr,
nullptr };
598 SECURITY_ATTRIBUTES saAttr;
601 ZeroMemory(&si,
sizeof(STARTUPINFO));
602 si.cb =
sizeof(STARTUPINFO);
605 saAttr.nLength =
sizeof(SECURITY_ATTRIBUTES);
606 saAttr.bInheritHandle =
true;
607 saAttr.lpSecurityDescriptor =
nullptr;
614 if (!CreatePipe(&p_stdin[0], &p_stdin[1], &saAttr, 0))
616 LOG(VB_GENERAL, LOG_ERR,
LOC_ERR +
"stdin pipe() failed");
622 if (!SetHandleInformation(p_stdin[1], HANDLE_FLAG_INHERIT, 0))
624 LOG(VB_SYSTEM, LOG_ERR,
LOC_ERR +
"stdin inheritance error");
629 si.hStdInput = p_stdin[0];
630 si.dwFlags |= STARTF_USESTDHANDLES;
639 if (!CreatePipe(&p_stdout[0], &p_stdout[1], &saAttr, 0))
641 LOG(VB_SYSTEM, LOG_ERR,
LOC_ERR +
"stdout pipe() failed");
647 if (!SetHandleInformation(p_stdout[0], HANDLE_FLAG_INHERIT, 0))
649 LOG(VB_SYSTEM, LOG_ERR,
LOC_ERR +
"stdout inheritance error");
654 si.hStdOutput = p_stdout[1];
655 si.dwFlags |= STARTF_USESTDHANDLES;
664 if (!CreatePipe(&p_stderr[0], &p_stderr[1], &saAttr, 0))
666 LOG(VB_SYSTEM, LOG_ERR,
LOC_ERR +
"stderr pipe() failed");
672 if (!SetHandleInformation(p_stderr[0], HANDLE_FLAG_INHERIT, 0))
674 LOG(VB_SYSTEM, LOG_ERR,
LOC_ERR +
"stderr inheritance error");
679 si.hStdError = p_stderr[1];
680 si.dwFlags |= STARTF_USESTDHANDLES;
689 cmd.prepend(
"cmd.exe /c ");
697 PROCESS_INFORMATION pi;
698 ZeroMemory(&pi,
sizeof(PROCESS_INFORMATION));
702 : SystemClock::time_point();
704 LPCWSTR pDir =
nullptr;
705 if (dir.length() > 0)
706 pDir = (LPCWSTR)dir.utf16();
709 sprintf(sCmdChar,
"%ls", (LPWSTR)sCmd.utf16() );
712 sprintf(pDirChar,
"%ls", pDir);
714 bool success = CreateProcess(
nullptr,
727 DWORD dwErr = GetLastError();
728 LOG(VB_SYSTEM, LOG_ERR,
729 QString(
"%1 CreateProcess() failed (%2)")
740 LOG(VB_SYSTEM, LOG_INFO,
741 QString(
"Managed child (Handle: %1) has started! "
742 "%2%3 command=%4, timeout=%5")
745 .arg(
GetSetting(
"RunInBackground") ?
"&" :
"")
This is a wrapper around QThread that does several additional things.
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
static void usleep(std::chrono::microseconds time)
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
void HandleWrite(int fd, QBuffer *buff)
MythSystemLegacyIOHandler(bool read)
void insert(int fd, QBuffer *buff)
void HandleRead(int fd, QBuffer *buff)
std::array< char, 65536 > m_readbuf
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
~MythSystemLegacyManager() override
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
void append(MythSystemLegacyUnix *ms)
void readDataReady(int fd)
QString & GetCommand(void)
QBuffer * GetBuffer(int index)
bool GetSetting(const char *setting)
void SetStatus(uint status)
QPointer< MythSystemLegacy > m_parent
QString & GetDirectory(void)
void SetCommand(const QString &cmd)
QStringList & GetArgs(void)
QString & GetLogCmd(void)
void run(void) override
Runs the Qt event loop unless we have a QRunnable, in which case we run the runnable run instead.
friend class MythSystemLegacySignalManager
void Signal(int sig) override
friend class MythSystemLegacyIOHandler
void Manage(void) override
void Fork(std::chrono::seconds timeout) override
friend class MythSystemLegacyManager
void JumpAbort(void) override
void Term(bool force=false) override
MythSystemLegacyWindows(MythSystemLegacy *parent)
bool ParseShell(const QString &cmd, QString &abscmd, QStringList &args) override
void readDataReady(int fd)
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual int IncrRef(void)
Increments reference count.
@ GENERIC_EXIT_OK
Exited with no error.
@ GENERIC_EXIT_RUNNING
Process is running.
@ GENERIC_EXIT_TIMEOUT
Process timed out.
@ GENERIC_EXIT_NOT_OK
Exited with error.
std::chrono::time_point< SystemClock > SystemTime
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
QMap< int, FDType_t * > FDMap_t
QList< QPointer< MythSystemLegacyUnix > > MSList_t
QMap< int, QBuffer * > PMap_t
void ShutdownMythSystemLegacy(void)
static MythSystemLegacyIOHandler * writeThread
static MythSystemLegacyIOHandler * readThread
static MythSystemLegacySignalManager * smanager
static MythSystemLegacyManager * manager
def read(device=None, features=[])
MythSystemLegacyWindows * ms