From fd032f103eb55d1efe2a62e4135c6e6bfea49839 Mon Sep 17 00:00:00 2001 From: Daniel Kristjansson Date: Sat, 1 Jun 2013 23:02:57 -0400 Subject: [PATCH] Close stdin after write in MythSystemLegacy. We only write to the program whatever has been sent in via Write() prior to calling Run(), but we never close the pipe. This is what was causing the stdin unit test for MythSystemLegacy to fail. --- mythtv/libs/libmythbase/mythsystemlegacy.cpp | 14 ++++++++-- mythtv/libs/libmythbase/mythsystemunix.cpp | 27 ++++++++++++++----- mythtv/libs/libmythbase/mythsystemunix.h | 1 + mythtv/libs/libmythbase/mythsystemwindows.cpp | 27 ++++++++++++++----- mythtv/libs/libmythbase/mythsystemwindows.h | 1 + .../test/test_mythsystem/test_mythsystem.h | 5 ++-- .../test_mythsystemlegacy.h | 6 ++--- 7 files changed, 62 insertions(+), 19 deletions(-) diff --git a/mythtv/libs/libmythbase/mythsystemlegacy.cpp b/mythtv/libs/libmythbase/mythsystemlegacy.cpp index ee4bca7395b..8d0dc406997 100644 --- a/mythtv/libs/libmythbase/mythsystemlegacy.cpp +++ b/mythtv/libs/libmythbase/mythsystemlegacy.cpp @@ -86,6 +86,13 @@ void MythSystemLegacy::SetCommand(const QString &command, uint flags) SetCommand(abscommand, args, flags); } + + if (m_settings["UseStdin"]) + m_stdbuff[0].open(QIODevice::WriteOnly); + if (m_settings["UseStdout"]) + m_stdbuff[1].open(QIODevice::ReadOnly); + if (m_settings["UseStderr"]) + m_stdbuff[2].open(QIODevice::ReadOnly); } @@ -390,13 +397,16 @@ QByteArray& MythSystemLegacy::ReadAllErr(void) return m_stdbuff[2].buffer(); } +/** This writes to the standard input of the program being run. + * All calls to this must be done before Run() is called. + * All calls after Run() is called are silently ignored. + */ int MythSystemLegacy::Write(const QByteArray &ba) { if (!GetSetting("UseStdin")) return 0; - m_stdbuff[0].buffer().append(ba.constData()); - return ba.size(); + return m_stdbuff[0].write(ba.constData()); } void MythSystemLegacy::HandlePreRun(void) diff --git a/mythtv/libs/libmythbase/mythsystemunix.cpp b/mythtv/libs/libmythbase/mythsystemunix.cpp index 17f363442e4..81a199ef65d 100644 --- a/mythtv/libs/libmythbase/mythsystemunix.cpp +++ b/mythtv/libs/libmythbase/mythsystemunix.cpp @@ -217,6 +217,17 @@ void MythSystemLegacyIOHandler::insert(int fd, QBuffer *buff) wake(); } +void MythSystemLegacyIOHandler::Wait(int fd) +{ + QMutexLocker locker(&m_pLock); + while (m_pMap.contains(fd)) + { + locker.unlock(); + usleep(10 * 1000); + locker.relock(); + } +} + void MythSystemLegacyIOHandler::remove(int fd) { m_pLock.lock(); @@ -444,8 +455,16 @@ void MythSystemLegacyManager::append(MythSystemLegacyUnix *ms) m_pMap.insert(ms->m_pid, ms); m_mapLock.unlock(); - if( ms->GetSetting("UseStdin") ) - writeThread->insert(ms->m_stdpipe[0], ms->GetBuffer(0)); + if (ms->m_stdpipe[0] >= 0) + { + QByteArray ba = ms->GetBuffer(0)->data(); + QBuffer wtb(&ba); + wtb.open(QIODevice::ReadOnly); + writeThread->insert(ms->m_stdpipe[0], &wtb); + writeThread->Wait(ms->m_stdpipe[0]); + writeThread->remove(ms->m_stdpipe[0]); + CLOSE(ms->m_stdpipe[0]); + } if( ms->GetSetting("UseStdout") ) { @@ -764,10 +783,6 @@ void MythSystemLegacyUnix::Fork(time_t timeout) LOG(VB_SYSTEM, LOG_DEBUG, QString("Launching: %1").arg(GetLogCmd())); - GetBuffer(0)->setBuffer(0); - GetBuffer(1)->setBuffer(0); - GetBuffer(2)->setBuffer(0); - int p_stdin[] = {-1,-1}; int p_stdout[] = {-1,-1}; int p_stderr[] = {-1,-1}; diff --git a/mythtv/libs/libmythbase/mythsystemunix.h b/mythtv/libs/libmythbase/mythsystemunix.h index 8eef979257b..33c979a80dc 100644 --- a/mythtv/libs/libmythbase/mythsystemunix.h +++ b/mythtv/libs/libmythbase/mythsystemunix.h @@ -35,6 +35,7 @@ class MythSystemLegacyIOHandler: public MThread void run(void); void insert(int fd, QBuffer *buff); + void Wait(int fd); void remove(int fd); void wake(); diff --git a/mythtv/libs/libmythbase/mythsystemwindows.cpp b/mythtv/libs/libmythbase/mythsystemwindows.cpp index fd8ad8795cd..0b2ad9263da 100644 --- a/mythtv/libs/libmythbase/mythsystemwindows.cpp +++ b/mythtv/libs/libmythbase/mythsystemwindows.cpp @@ -198,6 +198,17 @@ void MythSystemLegacyIOHandler::insert(HANDLE h, QBuffer *buff) wake(); } +void MythSystemLegacyIOHandler::Wait(HANDLE h) +{ + QMutexLocker locker(&m_pLock); + while (m_pMap.contains(h)) + { + locker.unlock(); + usleep(10 * 1000); + locker.relock(); + } +} + void MythSystemLegacyIOHandler::remove(HANDLE h) { m_pLock.lock(); @@ -402,8 +413,16 @@ void MythSystemLegacyManager::append(MythSystemLegacyWindows *ms) ChildListRebuild(); m_mapLock.unlock(); - if( ms->GetSetting("UseStdin") ) - writeThread->insert(ms->m_stdpipe[0], ms->GetBuffer(0)); + if (ms->m_stdpipe[0]) + { + QByteArray ba = ms->GetBuffer(0)->data(); + QBuffer wtb(&ba); + wtb.open(QIODevice::ReadOnly); + writeThread->insert(ms->m_stdpipe[0], &wtb); + writeThread->Wait(ms->m_stdpipe[0]); + writeThread->remove(ms->m_stdpipe[0]); + CLOSE(ms->m_stdpipe[0]); + } if( ms->GetSetting("UseStdout") ) { @@ -586,10 +605,6 @@ void MythSystemLegacyWindows::Fork(time_t timeout) LOG(VB_SYSTEM, LOG_DEBUG, QString("Launching: %1").arg(GetLogCmd())); - GetBuffer(0)->setBuffer(0); - GetBuffer(1)->setBuffer(0); - GetBuffer(2)->setBuffer(0); - HANDLE p_stdin[2] = { NULL, NULL }; HANDLE p_stdout[2] = { NULL, NULL }; HANDLE p_stderr[2] = { NULL, NULL }; diff --git a/mythtv/libs/libmythbase/mythsystemwindows.h b/mythtv/libs/libmythbase/mythsystemwindows.h index 74d191dec0f..45c6b2ce872 100644 --- a/mythtv/libs/libmythbase/mythsystemwindows.h +++ b/mythtv/libs/libmythbase/mythsystemwindows.h @@ -31,6 +31,7 @@ class MythSystemLegacyIOHandler: public MThread void run(void); void insert(HANDLE h, QBuffer *buff); + void Wait(HANDLE h); void remove(HANDLE h); void wake(); diff --git a/mythtv/libs/libmythbase/test/test_mythsystem/test_mythsystem.h b/mythtv/libs/libmythbase/test/test_mythsystem/test_mythsystem.h index 5c4b6962827..b99f9453e7f 100644 --- a/mythtv/libs/libmythbase/test/test_mythsystem/test_mythsystem.h +++ b/mythtv/libs/libmythbase/test/test_mythsystem/test_mythsystem.h @@ -141,10 +141,11 @@ class TestMythSystem: public QObject QByteArray in = QString(__FUNCTION__).toLatin1(); QScopedPointer cmd( MythSystem::Create(QString("cat - > %1").arg(tempfile.fileName()), - kMSStdIn)); + kMSStdIn | kMSRunShell)); cmd->GetStandardInputStream()->write(in); cmd->GetStandardInputStream()->close(); - cmd->Wait(); + cerr << "stdin_works -- Wait starting" << endl; + cmd->Wait(0); QVERIFY(cmd->GetExitCode() == 0); QByteArray out = tempfile.readAll(); QVERIFY(QString(out).contains(QString(in))); diff --git a/mythtv/libs/libmythbase/test/test_mythsystemlegacy/test_mythsystemlegacy.h b/mythtv/libs/libmythbase/test/test_mythsystemlegacy/test_mythsystemlegacy.h index bb0504c8105..cd36ca6c4a2 100644 --- a/mythtv/libs/libmythbase/test/test_mythsystemlegacy/test_mythsystemlegacy.h +++ b/mythtv/libs/libmythbase/test/test_mythsystemlegacy/test_mythsystemlegacy.h @@ -130,14 +130,14 @@ class TestMythSystemLegacy: public QObject // kMSStdIn -- allow access to stdin void stdin_works(void) { - MSKIP("stdin_works -- currently blocks forever"); QTemporaryFile tempfile; tempfile.open(); QByteArray in = QString(__FUNCTION__).toLatin1(); MythSystemLegacy cmd(QString("cat - > %1").arg(tempfile.fileName()), - kMSStdIn); + kMSStdIn | kMSRunShell); cmd.Write(in); - Go(cmd); + cmd.Run(); + cmd.Wait(); QVERIFY(cmd.GetStatus() == 0); QByteArray out = tempfile.readAll(); QVERIFY(QString(out).contains(QString(in)));