[mythtv] [PATCH] deadlock when opening video input

Kevin Hjelden mythtv at burntpopcorn.net
Fri Jan 16 02:37:11 EST 2004


This patch is to fix a deadlock when the video source is attempted to 
open and fails. tv_rec.cpp opens a thread to open the video source for 
recording, and then goes into an infinite loop waiting until the thread 
signals that the source is open. However, if the source fails to open, 
it simply returns (and doesn't retry) out of the thread causing the loop 
never to fail. This patch fixes that by having an error status in 
NuppelVideoRecoder that allows the function in tv_rec.cpp to abort if an 
error is thrown.

I'm not the best linux coder, so hopefully this doesn't cause too many 
problems. I've had it successfully running on my myth box for a month or 
so with no noticable problems.

Kevin
-------------- next part --------------
? mythtv/programs/mythfrontend/moc_rankchannels.cpp
? mythtv/programs/mythfrontend/moc_rankprograms.cpp
Index: mythtv/libs/libmythtv/NuppelVideoRecorder.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoRecorder.cpp,v
retrieving revision 1.152
diff -u -r1.152 NuppelVideoRecorder.cpp
--- mythtv/libs/libmythtv/NuppelVideoRecorder.cpp	7 Jan 2004 06:14:04 -0000	1.152
+++ mythtv/libs/libmythtv/NuppelVideoRecorder.cpp	16 Jan 2004 07:13:03 -0000
@@ -91,6 +91,7 @@
     childrenLive = false;
 
     recording = false;
+    errored = false;
 
     paused = false;
     pausewritethread = false;   
@@ -392,6 +393,11 @@
     return recording;
 }
 
+bool NuppelVideoRecorder::IsErrored(void)
+{
+    return errored;
+}
+
 long long NuppelVideoRecorder::GetFramesWritten(void)
 {
     return framesWritten;
@@ -791,6 +797,7 @@
     if (lzo_init() != LZO_E_OK)
     {
         cerr << "lzo_init() failed, exiting\n";
+        errored = true;
         return;
     }
 
@@ -815,18 +822,21 @@
     {
         cerr << "Cannot open '" << ringBuffer->GetFilename() << "' for "
              << "writing, exiting\n";
+        errored = true;
         return;
     }
 
     if (childrenLive)
     {
         cerr << "Error: children are already alive\n";
+        errored = true;
         return;
     }
 
     if (SpawnChildren() < 0)
     {
         cerr << "Couldn't spawn children\n";
+        errored = true;
         return;
     }
 
@@ -848,13 +858,20 @@
     if (getuid() == 0)
         nice(-10);
 
+    int retries = 0;
     fd = open(videodevice.ascii(), O_RDWR);
-    if (fd <= 0)
+    while (fd <= 0)
     {
-        cerr << "Can't open video device: " << videodevice << endl;
-        perror("open video:");
-        KillChildren();
-        return;
+        usleep(30000);
+        fd = open(videodevice.ascii(), O_RDWR);
+        if (retries++ > 5)
+        { 
+            cerr << "Can't open video device: " << videodevice << endl;
+            perror("open video:");
+            KillChildren();
+            errored = true;
+            return;
+        }
     }
 
     usingv4l2 = true;
Index: mythtv/libs/libmythtv/NuppelVideoRecorder.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoRecorder.h,v
retrieving revision 1.66
diff -u -r1.66 NuppelVideoRecorder.h
--- mythtv/libs/libmythtv/NuppelVideoRecorder.h	7 Jan 2004 06:14:04 -0000	1.66
+++ mythtv/libs/libmythtv/NuppelVideoRecorder.h	16 Jan 2004 07:13:03 -0000
@@ -64,6 +64,7 @@
     void WaitForPause(void);   
  
     bool IsRecording(void);
+    bool IsErrored(void);
    
     long long GetFramesWritten(void); 
 
@@ -193,6 +194,7 @@
     pthread_t vbi_tid;
 
     bool recording;
+    bool errored;
 
     int keyframedist;
     vector<struct seektable_entry> *seektable;
Index: mythtv/libs/libmythtv/hdtvrecorder.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/hdtvrecorder.h,v
retrieving revision 1.15
diff -u -r1.15 hdtvrecorder.h
--- mythtv/libs/libmythtv/hdtvrecorder.h	7 Jan 2004 06:14:04 -0000	1.15
+++ mythtv/libs/libmythtv/hdtvrecorder.h	16 Jan 2004 07:13:03 -0000
@@ -32,6 +32,7 @@
     bool GetPause(void);
     void WaitForPause(void);
     bool IsRecording(void);
+    bool IsErrored(void) { return false; }
 
     long long GetFramesWritten(void);
 
Index: mythtv/libs/libmythtv/mpegrecorder.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/mpegrecorder.h,v
retrieving revision 1.10
diff -u -r1.10 mpegrecorder.h
--- mythtv/libs/libmythtv/mpegrecorder.h	7 Jan 2004 06:14:04 -0000	1.10
+++ mythtv/libs/libmythtv/mpegrecorder.h	16 Jan 2004 07:13:03 -0000
@@ -31,6 +31,7 @@
     bool GetPause(void);
     void WaitForPause(void);
     bool IsRecording(void);
+    bool IsErrored(void) { return false; }
 
     long long GetFramesWritten(void);
 
Index: mythtv/libs/libmythtv/recorderbase.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/recorderbase.h,v
retrieving revision 1.9
diff -u -r1.9 recorderbase.h
--- mythtv/libs/libmythtv/recorderbase.h	7 Jan 2004 06:14:04 -0000	1.9
+++ mythtv/libs/libmythtv/recorderbase.h	16 Jan 2004 07:13:03 -0000
@@ -45,6 +45,7 @@
     virtual void WaitForPause(void) = 0;
 
     virtual bool IsRecording(void) = 0;
+    virtual bool IsErrored(void) = 0;
 
     virtual long long GetFramesWritten(void) = 0;
     
Index: mythtv/libs/libmythtv/tv_rec.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/tv_rec.cpp,v
retrieving revision 1.126
diff -u -r1.126 tv_rec.cpp
--- mythtv/libs/libmythtv/tv_rec.cpp	9 Jan 2004 21:02:13 -0000	1.126
+++ mythtv/libs/libmythtv/tv_rec.cpp	16 Jan 2004 07:13:04 -0000
@@ -485,13 +487,25 @@
         SetVideoFiltersForChannel(channel, channel->GetCurrentName());
         pthread_create(&encode, NULL, SpawnEncode, nvr);
 
-        while (!nvr->IsRecording())
+        while (!nvr->IsRecording() && !nvr->IsErrored()) // (20 seconds @ usleep(50))
             usleep(50);
 
         // evil.
-        channel->SetFd(nvr->GetVideoFd());
+        if (nvr->IsRecording())
+        {
+            channel->SetFd(nvr->GetVideoFd());
+            SetVideoFiltersForChannel(channel, channel->GetCurrentName());
 
-        frameRate = nvr->GetFrameRate();
+            frameRate = nvr->GetFrameRate();
+        }
+        else
+        {
+            FinishedRecording();
+            killRecordingFile = true;
+            closeRecorder = true;
+            tmpInternalState = kState_None;
+        }
     }
 
     if (closeRecorder)


More information about the mythtv-dev mailing list