Switch to side-by-side view

--- a/src/mediaserver/cdplugins/cmdtalk.cpp
+++ b/src/mediaserver/cdplugins/cmdtalk.cpp
@@ -28,26 +28,49 @@
 
 using namespace std;
 
+class TimeoutExcept {};
+
+class Canceler : public ExecCmdAdvise {
+public:
+    Canceler(int tmsecs) 
+        : m_timeosecs(tmsecs) {}
+
+    virtual void newData(int cnt) {
+        if (m_starttime && (time(0) - m_starttime) > m_timeosecs) {
+            throw TimeoutExcept();
+        }
+    }
+
+    void reset() {
+        m_starttime = time(0);
+    }
+    int m_timeosecs;
+    time_t m_starttime{0};
+};
+
 class CmdTalk::Internal {
 public:
-    Internal()
-	: cmd(0) {
-    }
+    Internal(int timeosecs)
+	: m_cancel(timeosecs) {}
+
     ~Internal() {
 	delete cmd;
     }
+
     bool readDataElement(string& name, string &data);
 
     bool talk(const pair<string, string>& arg0,
 	      const unordered_map<string, string>& args,
 	      unordered_map<string, string>& rep);
-    ExecCmd *cmd;
+
+    ExecCmd *cmd{0};
+    Canceler m_cancel;
     std::mutex mmutex;
 };
 
-CmdTalk::CmdTalk()
-{
-    m = new Internal;
+CmdTalk::CmdTalk(int timeosecs)
+{
+    m = new Internal(timeosecs);
 }
 CmdTalk::~CmdTalk()
 {
@@ -63,7 +86,8 @@
 
     delete m->cmd;
     m->cmd = new ExecCmd;
-    
+    m->cmd->setAdvise(&m->m_cancel);
+
     for (const auto& it : env) {
 	m->cmd->putenv(it);
     }
@@ -96,9 +120,16 @@
 {
     string ibuf;
 
-    // Read name and length
-    if (cmd->getline(ibuf) <= 0) {
-        LOGERR("CmdTalk: getline error\n" );
+    m_cancel.reset();
+    try {
+        // Read name and length
+        if (cmd->getline(ibuf) <= 0) {
+            LOGERR("CmdTalk: getline error\n" );
+            return false;
+        }
+    } catch (TimeoutExcept) {
+        LOGINF("CmdTalk:readDataElement: fatal timeout (" <<
+               m_cancel.m_timeosecs << " S)\n");
         return false;
     }