Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] [PATCH] NPTL



Hi,

Starting from Werners patch for signal handling I spent the whole
day debugging the cutmarks jumping problems that showed up when
using NPTL. The culprit for the hangs was a usleep(1) inside a mutex
protected section. With the attached patches jumping between
cutmarks, starting/pausing/stopping replays and properly quitting
vdr now work fine for me. Even if it works it for sure doesn't fix
all problems, I assume there are way more mutex locks necessary.

vdr-1.2.6-fpic.patch - add -fPIC and source Make.config in subdirectories
vdr-1.2.6-werner.diff - the patch from Werner adapted for 1.2.6
vdr-1.2.6-13threads.diff - thread.[ch] from vdr-1.3.9
vdr-1.2.6-threadcancelsegv.diff - fix a segfault
vdr-1.2.6-fixthreads.diff - the actual NPTL fixes
vdr-1.2.6-thread-debug.diff - not strictly needed. for debugging.

I'm going to put a package for SUSE9.1 with the patches applied into
ftp://ftp.suse.com/pub/people/lnussel/vdr/

cu
Ludwig

-- 
(o_  Ludwig.Nussel@gmx.de
//\  PGP Key ID: FF8135CE
V_/_ ICQ:        52166811
Index: vdr-1.2.6/libdtv/liblx/Makefile
===================================================================
--- vdr-1.2.6.orig/libdtv/liblx/Makefile	2003-01-26 14:54:05.000000000 +0100
+++ vdr-1.2.6/libdtv/liblx/Makefile	2004-01-15 23:20:40.000000000 +0100
@@ -28,9 +28,12 @@
 #
 #
 CC ?= gcc
-CFLAGS ?= -O2 -g -pedantic -Wmissing-prototypes -Wstrict-prototypes \
-         -Wimplicit -D__USE_FIXED_PROTOTYPES__ # -DDEBUG
+CFLAGS ?= -O2 -g
+
+-include ../../Make.config
 
+CFLAGS += -fPIC -pedantic -Wmissing-prototypes -Wstrict-prototypes \
+         -Wimplicit -D__USE_FIXED_PROTOTYPES__ # -DDEBUG
 
 AR = ar
 ARFLAGS = r
Index: vdr-1.2.6/libdtv/libsi/Makefile
===================================================================
--- vdr-1.2.6.orig/libdtv/libsi/Makefile	2002-12-13 15:53:55.000000000 +0100
+++ vdr-1.2.6/libdtv/libsi/Makefile	2004-01-15 23:20:26.000000000 +0100
@@ -31,7 +31,11 @@
 .DELETE_ON_ERROR:
 
 CC ?= gcc
-CFLAGS ?= -O2 -g -Wmissing-prototypes -Wstrict-prototypes \
+CFLAGS ?= -O2 -g
+
+-include ../../Make.config
+
+CFLAGS += -fPIC -Wmissing-prototypes -Wstrict-prototypes \
          -DNAPI -Wimplicit -D__USE_FIXED_PROTOTYPES__ # -ansi -pedantic 
 
 INCDIRS = -Iinclude -I../include
Index: vdr-1.2.6/thread.c
===================================================================
--- vdr-1.2.6.orig/thread.c	2004-06-06 13:46:22.585349990 +0000
+++ vdr-1.2.6/thread.c	2004-06-06 13:48:56.915169506 +0000
@@ -18,6 +18,8 @@
 #include <unistd.h>
 #include "tools.h"
 
+extern sigset_t TheSigset;	// The signals handled in VDR
+
 // --- cCondVar --------------------------------------------------------------
 
 cCondVar::cCondVar(void)
@@ -128,10 +130,6 @@
 
 cThread::cThread(const char *Description)
 {
-  if (!signalHandlerInstalled) {
-     signal(SIGIO, SignalHandler);
-     signalHandlerInstalled = true;
-     }
   running = false;
   parentTid = childTid = 0;
   description = NULL;
@@ -162,6 +160,17 @@
 
 void *cThread::StartThread(cThread *Thread)
 {
+  (void)pthread_sigmask(SIG_BLOCK, &TheSigset, (sigset_t*)0);
+  if (!signalHandlerInstalled) {
+    sigset_t sigset;
+    sigemptyset(&sigset);
+    sigaddset(&sigset, SIGIO);
+
+    signal(SIGIO, SignalHandler);
+    (void)pthread_sigmask(SIG_UNBLOCK, &sigset, (sigset_t*)0);
+
+    signalHandlerInstalled = true;
+  }
   Thread->childTid = pthread_self();
   if (Thread->description)
      dsyslog("%s thread started (pid=%d, tid=%ld)", Thread->description, getpid(), Thread->childTid);
Index: vdr-1.2.6/vdr.c
===================================================================
--- vdr-1.2.6.orig/vdr.c	2004-06-06 13:42:39.806875289 +0000
+++ vdr-1.2.6/vdr.c	2004-06-06 13:47:14.765290861 +0000
@@ -66,13 +66,84 @@
 
 static int Interrupted = 0;
 
+sigset_t TheSigset;
+
+static struct sigaction SavedSIGHUP;
+static struct sigaction SavedSIGINT;
+static struct sigaction SavedSIGTERM;
+static struct sigaction SavedSIGPIPE;
+static struct sigaction SavedSIGALRM;
+
+static void SetSignal(int sig, struct sigaction &old, sighandler_t handler)
+{
+  do {
+     if (sigaction(sig, NULL, &old) == 0)
+	break;
+     }
+  while (errno == EINTR);
+
+  if (old.sa_handler != handler)
+     {
+     struct sigaction act;
+     sigset_t sigset;
+
+     act.sa_handler = handler;
+     sigemptyset(&act.sa_mask);
+     act.sa_flags = SA_RESTART;
+     if (sig == SIGALRM)
+	act.sa_flags |= SA_ONESHOT;
+     do {
+	if (sigaction(sig, &act, NULL) == 0)
+	   break;
+        }
+     while (errno == EINTR);
+
+     sigaddset(&TheSigset, sig); // Remember the signals
+
+     sigemptyset(&sigset);
+     sigaddset(&sigset, sig);
+     sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+     }
+}
+
+static void ResetSignal(int sig, struct sigaction &old)
+{
+  struct sigaction cur;
+
+  do {
+     if (sigaction(sig, NULL, &cur) == 0)
+	break;
+     }
+  while (errno == EINTR);
+
+  if (old.sa_handler == cur.sa_handler)
+     {
+     do {
+	if (sigaction(sig, &old, NULL) == 0)
+	   break;
+        }
+     while (errno == EINTR);
+     }
+}
+
+static void IgnoreSignal(int sig)
+{
+  sigset_t sigset;
+  sigemptyset(&sigset);
+  sigaddset(&sigset, sig);
+  (void)pthread_sigmask(SIG_BLOCK, &sigset, (sigset_t*)0);
+}
+
 static void SignalHandler(int signum)
 {
   if (signum != SIGPIPE) {
      Interrupted = signum;
      Interface->Interrupt();
      }
-  signal(signum, SignalHandler);
+//
+// Only required if SA_ONESHOT is set in sa_flags
+// signal(signum, SignalHandler);
+//
 }
 
 static void Watchdog(int signum)
@@ -602,13 +673,13 @@
   cSIProcessor::Read();
 
   // Signal handlers:
-
-  if (signal(SIGHUP,  SignalHandler) == SIG_IGN) signal(SIGHUP,  SIG_IGN);
-  if (signal(SIGINT,  SignalHandler) == SIG_IGN) signal(SIGINT,  SIG_IGN);
-  if (signal(SIGTERM, SignalHandler) == SIG_IGN) signal(SIGTERM, SIG_IGN);
-  if (signal(SIGPIPE, SignalHandler) == SIG_IGN) signal(SIGPIPE, SIG_IGN);
+  SetSignal(SIGHUP,  SavedSIGHUP,  SignalHandler);
+  SetSignal(SIGINT,  SavedSIGINT,  SignalHandler);
+  SetSignal(SIGTERM, SavedSIGTERM, SignalHandler);
+  SetSignal(SIGPIPE, SavedSIGPIPE, SignalHandler);
   if (WatchdogTimeout > 0)
-     if (signal(SIGALRM, Watchdog)   == SIG_IGN) signal(SIGALRM, SIG_IGN);
+     SetSignal(SIGALRM, SavedSIGALRM, Watchdog);
+  IgnoreSignal(SIGIO);
 
   // Watchdog:
 
@@ -963,6 +1034,11 @@
   Setup.Save();
   cDevice::Shutdown();
   PluginManager.Shutdown(true);
+  ResetSignal(SIGHUP,  SavedSIGHUP);
+  ResetSignal(SIGINT,  SavedSIGINT);
+  ResetSignal(SIGTERM, SavedSIGTERM);
+  ResetSignal(SIGPIPE, SavedSIGPIPE);
+  ResetSignal(SIGALRM, SavedSIGALRM);
   if (WatchdogTimeout > 0)
      dsyslog("max. latency time %d seconds", MaxLatencyTime);
   isyslog("exiting");
Index: vdr-1.2.6/thread.c
===================================================================
--- vdr-1.2.6.orig/thread.c	2004-06-06 13:42:39.658912622 +0000
+++ vdr-1.2.6/thread.c	2004-06-06 13:46:22.585349990 +0000
@@ -9,7 +9,9 @@
 
 #include "thread.h"
 #include <errno.h>
+#include <malloc.h>
 #include <signal.h>
+#include <stdarg.h>
 #include <sys/resource.h>
 #include <sys/time.h>
 #include <sys/wait.h>
@@ -30,7 +32,7 @@
 
 void cCondVar::Wait(cMutex &Mutex)
 {
-  if (Mutex.locked && Mutex.lockingPid == getpid()) {
+  if (Mutex.locked) {
      int locked = Mutex.locked;
      Mutex.locked = 0; // have to clear the locked count here, as pthread_cond_wait
                        // does an implizit unlock of the mutex
@@ -43,7 +45,7 @@
 {
   bool r = true; // true = condition signaled false = timeout
 
-  if (Mutex.locked && Mutex.lockingPid == getpid()) {
+  if (Mutex.locked) {
      struct timeval now;                   // unfortunately timedwait needs the absolute time, not the delta :-(
      if (gettimeofday(&now, NULL) == 0) {  // get current time
         now.tv_usec += TimeoutMs * 1000;   // add the timeout
@@ -61,7 +63,6 @@
         if (pthread_cond_timedwait(&cond, &Mutex.mutex, &abstime) == ETIMEDOUT)
            r = false;
         Mutex.locked = locked;
-        Mutex.lockingPid = getpid();
         }
      }
   return r;
@@ -83,9 +84,9 @@
 
 cMutex::cMutex(void)
 {
-  lockingPid = 0;
   locked = 0;
-  pthread_mutex_init(&mutex, NULL);
+  pthread_mutexattr_t attr = { PTHREAD_MUTEX_ERRORCHECK_NP };
+  pthread_mutex_init(&mutex, &attr);
 }
 
 cMutex::~cMutex()
@@ -95,19 +96,14 @@
 
 void cMutex::Lock(void)
 {
-  if (getpid() != lockingPid || !locked) {
-     pthread_mutex_lock(&mutex);
-     lockingPid = getpid();
-     }
+  pthread_mutex_lock(&mutex);
   locked++;
 }
 
 void cMutex::Unlock(void)
 {
- if (!--locked) {
-    lockingPid = 0;
+ if (!--locked)
     pthread_mutex_unlock(&mutex);
-    }
 }
 
 // --- cRwlock --------------------------------------------------------------
@@ -130,18 +126,33 @@
 bool cThread::signalHandlerInstalled = false;
 bool cThread::emergencyExitRequested = false;
 
-cThread::cThread(void)
+cThread::cThread(const char *Description)
 {
   if (!signalHandlerInstalled) {
      signal(SIGIO, SignalHandler);
      signalHandlerInstalled = true;
      }
   running = false;
-  parentPid = threadPid = 0;
+  parentTid = childTid = 0;
+  description = NULL;
+  SetDescription(Description);
 }
 
 cThread::~cThread()
 {
+  free(description);
+}
+
+void cThread::SetDescription(const char *Description, ...)
+{
+  free(description);
+  description = NULL;
+  if (Description) {
+     va_list ap;
+     va_start(ap, Description);
+     vasprintf(&description, Description, ap);
+     va_end(ap);
+     }
 }
 
 void cThread::SignalHandler(int signum)
@@ -151,8 +162,13 @@
 
 void *cThread::StartThread(cThread *Thread)
 {
-  Thread->threadPid = getpid();
+  Thread->childTid = pthread_self();
+  if (Thread->description)
+     dsyslog("%s thread started (pid=%d, tid=%ld)", Thread->description, getpid(), Thread->childTid);
   Thread->Action();
+  if (Thread->description)
+     dsyslog("%s thread ended (pid=%d, tid=%ld)", Thread->description, getpid(), Thread->childTid);
+  Thread->childTid = 0;
   return NULL;
 }
 
@@ -160,9 +176,10 @@
 {
   if (!running) {
      running = true;
-     parentPid = getpid();
-     pthread_create(&thread, NULL, (void *(*) (void *))&StartThread, (void *)this);
-     pthread_setschedparam(thread, SCHED_RR, 0);
+     parentTid = pthread_self();
+     pthread_create(&childTid, NULL, (void *(*) (void *))&StartThread, (void *)this);
+     pthread_detach(childTid); // auto-reap
+     pthread_setschedparam(childTid, SCHED_RR, 0);
      usleep(10000); // otherwise calling Active() immediately after Start() causes a "pure virtual method called" error
      }
   return true; //XXX return value of pthread_create()???
@@ -170,12 +187,21 @@
 
 bool cThread::Active(void)
 {
-  if (threadPid) {
-     if (kill(threadPid, SIGIO) < 0) { // couldn't find another way of checking whether the thread is still running - any ideas?
-        if (errno == ESRCH)
-           threadPid = 0;
-        else
+  if (childTid) {
+     //
+     // Single UNIX Spec v2 says:
+     //
+     // The pthread_kill() function is used to request
+     // that a signal be delivered to the specified thread.
+     //
+     // As in kill(), if sig is zero, error checking is
+     // performed but no signal is actually sent.
+     //
+     int err;
+     if ((err = pthread_kill(childTid, 0)) != 0) {
+        if (err != ESRCH)
            LOG_ERROR;
+        childTid = 0;
         }
      else
         return true;
@@ -192,14 +218,14 @@
             return;
          usleep(10000);
          }
-     esyslog("ERROR: thread %d won't end (waited %d seconds) - cancelling it...", threadPid, WaitSeconds);
+     esyslog("ERROR: thread %ld won't end (waited %d seconds) - cancelling it...", childTid, WaitSeconds);
      }
-  pthread_cancel(thread);
+  pthread_cancel(childTid);
 }
 
 void cThread::WakeUp(void)
 {
-  kill(parentPid, SIGIO); // makes any waiting 'select()' call return immediately
+  pthread_kill(parentTid, SIGIO); // makes any waiting 'select()' call return immediately
 }
 
 bool cThread::EmergencyExit(bool Request)
Index: vdr-1.2.6/thread.h
===================================================================
--- vdr-1.2.6.orig/thread.h	2004-06-06 13:42:39.659912370 +0000
+++ vdr-1.2.6/thread.h	2004-06-06 13:46:45.959661351 +0000
@@ -40,7 +40,6 @@
   friend class cCondVar;
 private:
   pthread_mutex_t mutex;
-  pid_t lockingPid;
   int locked;
 public:
   cMutex(void);
@@ -79,10 +78,10 @@
 class cThread {
   friend class cThreadLock;
 private:
-  pthread_t thread;
+  pthread_t parentTid, childTid;
   cMutex mutex;
-  pid_t parentPid, threadPid;
   bool running;
+  char *description;
   static bool emergencyExitRequested;
   static bool signalHandlerInstalled;
   static void SignalHandler(int signum);
@@ -94,8 +93,9 @@
   virtual void Action(void) = 0;
   void Cancel(int WaitSeconds = 0);
 public:
-  cThread(void);
+  cThread(const char *Description = NULL);
   virtual ~cThread();
+  void SetDescription(const char *Description, ...);
   bool Start(void);
   bool Active(void);
   static bool EmergencyExit(bool Request = false);
Index: vdr-1.2.6/thread.c
===================================================================
--- vdr-1.2.6.orig/thread.c	2004-06-06 14:45:48.855827380 +0000
+++ vdr-1.2.6/thread.c	2004-06-06 14:47:05.362325860 +0000
@@ -220,6 +220,7 @@
 
 void cThread::Cancel(int WaitSeconds)
 {
+  if(!running) return;
   running = false;
   if (WaitSeconds > 0) {
      for (time_t t0 = time(NULL) + WaitSeconds; time(NULL) < t0; ) {
Index: vdr-1.2.6/dvbdevice.c
===================================================================
--- vdr-1.2.6.orig/dvbdevice.c	2004-06-06 22:08:12.019760921 +0200
+++ vdr-1.2.6/dvbdevice.c	2004-06-06 22:15:21.354774391 +0200
@@ -462,6 +462,7 @@
 
 cDvbDevice::cDvbDevice(int n)
 {
+  LOCK_THREAD;
   dvbTuner = NULL;
   frontendType = fe_type_t(-1); // don't know how else to initialize this - there is no FE_UNKNOWN
   siProcessor = NULL;
@@ -540,6 +541,7 @@
 
 cDvbDevice::~cDvbDevice()
 {
+  LOCK_THREAD;
   delete spuDecoder;
   delete siProcessor;
   delete scanner;
@@ -591,6 +593,7 @@
 
 void cDvbDevice::MakePrimaryDevice(bool On)
 {
+  LOCK_THREAD;
   if (HasDecoder())
      cDvbOsd::SetDvbDevice(On ? this : NULL);
 }
@@ -602,11 +605,13 @@
 
 cOsdBase *cDvbDevice::NewOsd(int x, int y)
 {
+  LOCK_THREAD;
   return new cDvbOsd(x, y);
 }
 
 cSpuDecoder *cDvbDevice::GetSpuDecoder(void)
 {
+  LOCK_THREAD;
   if (!spuDecoder && IsPrimaryDevice())
      spuDecoder = new cDvbSpuDecoder();
   return spuDecoder;
@@ -614,6 +619,7 @@
 
 bool cDvbDevice::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY)
 {
+  LOCK_THREAD;
   if (devVideoIndex < 0)
      return false;
   char buffer[PATH_MAX];
@@ -713,12 +719,14 @@
 
 void cDvbDevice::SetVideoFormat(bool VideoFormat16_9)
 {
+  LOCK_THREAD;
   if (HasDecoder())
      CHECK(ioctl(fd_video, VIDEO_SET_FORMAT, VideoFormat16_9 ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3));
 }
 
 eVideoSystem cDvbDevice::GetVideoSystem(void)
 {
+  LOCK_THREAD;
   eVideoSystem VideoSytem = vsPAL;
   video_size_t vs;
   if (ioctl(fd_video, VIDEO_GET_SIZE, &vs) == 0) {
@@ -735,6 +743,7 @@
 
 bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
 {
+  LOCK_THREAD;
   if (Handle->pid) {
      dmx_pes_filter_params pesFilterParams;
      memset(&pesFilterParams, 0, sizeof(pesFilterParams));
@@ -775,6 +784,7 @@
 
 void cDvbDevice::TurnOffLiveMode(void)
 {
+  LOCK_THREAD;
   // Avoid noise while switching:
 
   CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, true));
@@ -838,6 +848,7 @@
 
 bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
 {
+  LOCK_THREAD;
   bool IsEncrypted = Channel->Ca() > CACONFBASE && !ciHandler; // only LL-firmware can do non-live CA channels
 
   bool DoTune = !dvbTuner->IsTunedTo(Channel);
@@ -915,6 +926,7 @@
 
 void cDvbDevice::SetVolumeDevice(int Volume)
 {
+  LOCK_THREAD;
   if (HasDecoder()) {
      audio_mixer_t am;
      am.volume_left = am.volume_right = Volume;
@@ -946,6 +958,7 @@
 
 void cDvbDevice::SetAudioTrackDevice(int Index)
 {
+  LOCK_THREAD;
   if (0 <= Index && Index < NumAudioTracksDevice()) {
      int Pid = Index ? aPid2 : aPid1;
      pidHandles[ptAudio].pid = Pid;
@@ -964,6 +977,7 @@
 
 bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
 {
+  LOCK_THREAD;
   if (PlayMode != pmExtern_THIS_SHOULD_BE_AVOIDED && fd_video < 0 && fd_audio < 0) {
      // reopen the devices
      fd_video = DvbOpen(DEV_DVB_VIDEO,  CardIndex(), O_RDWR | O_NONBLOCK);
@@ -1028,6 +1042,7 @@
 
 int64_t cDvbDevice::GetSTC(void)
 {
+  LOCK_THREAD;
   if (fd_stc >= 0) {
      struct dmx_stc stc;
      stc.num = 0;
@@ -1042,12 +1057,14 @@
 
 void cDvbDevice::TrickSpeed(int Speed)
 {
+  LOCK_THREAD;
   if (fd_video >= 0)
      CHECK(ioctl(fd_video, VIDEO_SLOWMOTION, Speed));
 }
 
 void cDvbDevice::Clear(void)
 {
+  LOCK_THREAD;
   if (fd_video >= 0)
      CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER));
   if (fd_audio >= 0)
@@ -1057,6 +1074,7 @@
 
 void cDvbDevice::Play(void)
 {
+  LOCK_THREAD;
   if (playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) {
      if (fd_audio >= 0)
         CHECK(ioctl(fd_audio, AUDIO_CONTINUE));
@@ -1072,6 +1090,7 @@
 
 void cDvbDevice::Freeze(void)
 {
+  LOCK_THREAD;
   if (playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) {
      if (fd_audio >= 0)
         CHECK(ioctl(fd_audio, AUDIO_PAUSE));
@@ -1087,6 +1106,7 @@
 
 void cDvbDevice::Mute(void)
 {
+  LOCK_THREAD;
   if (fd_audio >= 0) {
      CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false));
      CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, true));
@@ -1096,6 +1116,7 @@
 
 void cDvbDevice::StillPicture(const uchar *Data, int Length)
 {
+  LOCK_THREAD;
 /* Using the VIDEO_STILLPICTURE ioctl call would be the
    correct way to display a still frame, but unfortunately this
    doesn't work with frames from VDR. So let's do pretty much the
@@ -1200,6 +1221,7 @@
 
 int cDvbDevice::PlayVideo(const uchar *Data, int Length)
 {
+  LOCK_THREAD;
   int fd = (playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) ? fd_audio : fd_video;
   if (fd >= 0)
      return write(fd, Data, Length);
@@ -1208,12 +1230,14 @@
 
 void cDvbDevice::PlayAudio(const uchar *Data, int Length)
 {
+  LOCK_THREAD;
   //XXX actually this function will only be needed to implement replaying AC3 over the DVB card's S/PDIF
   cDevice::PlayAudio(Data, Length);
 }
 
 bool cDvbDevice::OpenDvr(void)
 {
+  LOCK_THREAD;
   CloseDvr();
   fd_dvr = DvbOpen(DEV_DVB_DVR, CardIndex(), O_RDONLY | O_NONBLOCK, true);
   if (fd_dvr >= 0)
@@ -1223,6 +1247,7 @@
 
 void cDvbDevice::CloseDvr(void)
 {
+  LOCK_THREAD;
   if (fd_dvr >= 0) {
      close(fd_dvr);
      fd_dvr = -1;
@@ -1233,6 +1258,7 @@
 
 bool cDvbDevice::GetTSPacket(uchar *&Data)
 {
+  LOCK_THREAD;
   if (tsBuffer) {
      int r = tsBuffer->Read();
      if (r >= 0) {
Index: vdr-1.2.6/dvbplayer.c
===================================================================
--- vdr-1.2.6.orig/dvbplayer.c	2004-06-06 22:08:12.020760702 +0200
+++ vdr-1.2.6/dvbplayer.c	2004-06-06 22:11:23.696045913 +0200
@@ -423,14 +423,15 @@
   running = true;
   while (running && (NextFile() || readIndex >= 0 || ringBuffer->Available())) {
         cPoller Poller;
-        if (DevicePoll(Poller, 100)) {
-
-           LOCK_THREAD;
+        if (DevicePoll(Poller, -1)) {
 
            // Read the next frame from the file:
 
            if (!readFrame && (replayFile >= 0 || readIndex >= 0)) {
               if (playMode != pmStill) {
+
+		 LOCK_THREAD;
+
                  if (!nonBlockingFileReader->Reading()) {
                     if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) {
                        uchar FileNumber;
@@ -491,12 +492,14 @@
                     break;
                     }
                  }
-              else//XXX
-                 usleep(1); // this keeps the CPU load low
-              }
+              else
+		pause(); // block until WakeUp()
+	      }
 
            // Store the frame in the buffer:
 
+	   LOCK_THREAD;
+
            if (readFrame) {
               if (ringBuffer->Put(readFrame))
                  readFrame = NULL;
@@ -577,6 +580,7 @@
      DevicePlay();
      playMode = pmPlay;
      playDir = pdForward;
+     WakeUp();
     }
 }
 
Index: vdr-1.2.6/thread.c
===================================================================
--- vdr-1.2.6.orig/thread.c	2004-06-06 22:08:12.018761140 +0200
+++ vdr-1.2.6/thread.c	2004-06-06 22:15:21.352774827 +0200
@@ -155,22 +155,21 @@
 
 void cThread::SignalHandler(int signum)
 {
+  dsyslog("%s:%d (%s) Tid: %ld Sig: %d\n",__FILE__, __LINE__, __FUNCTION__, pthread_self(), signum);
   signal(signum, SignalHandler);
 }
 
 void *cThread::StartThread(cThread *Thread)
 {
-  (void)pthread_sigmask(SIG_BLOCK, &TheSigset, (sigset_t*)0);
   if (!signalHandlerInstalled) {
-    sigset_t sigset;
-    sigemptyset(&sigset);
-    sigaddset(&sigset, SIGIO);
-
     signal(SIGIO, SignalHandler);
-    (void)pthread_sigmask(SIG_UNBLOCK, &sigset, (sigset_t*)0);
-
     signalHandlerInstalled = true;
   }
+  sigset_t sigset;
+  sigemptyset(&sigset);
+  sigaddset(&sigset, SIGIO);
+  (void)pthread_sigmask(SIG_UNBLOCK, &sigset, (sigset_t*)0);
+
   Thread->childTid = pthread_self();
   if (Thread->description)
      dsyslog("%s thread started (pid=%d, tid=%ld)", Thread->description, getpid(), Thread->childTid);
@@ -222,6 +221,7 @@
 {
   if(!running) return;
   running = false;
+  WakeUp();
   if (WaitSeconds > 0) {
      for (time_t t0 = time(NULL) + WaitSeconds; time(NULL) < t0; ) {
          if (!Active())
@@ -235,7 +235,8 @@
 
 void cThread::WakeUp(void)
 {
-  pthread_kill(parentTid, SIGIO); // makes any waiting 'select()' call return immediately
+  if(childTid)
+    pthread_kill(childTid, SIGIO); // makes any waiting 'select()' call return immediately
 }
 
 bool cThread::EmergencyExit(bool Request)
Index: vdr-1.2.6/cutter.c
===================================================================
--- vdr-1.2.6.orig/cutter.c	2004-06-06 22:13:38.591261881 +0200
+++ vdr-1.2.6/cutter.c	2004-06-06 22:13:57.864031819 +0200
@@ -32,6 +32,7 @@
   };
 
 cCuttingThread::cCuttingThread(const char *FromFileName, const char *ToFileName)
+  : cThread("cCuttingThread")
 {
   error = NULL;
   active = false;
Index: vdr-1.2.6/device.c
===================================================================
--- vdr-1.2.6.orig/device.c	2004-06-06 22:13:38.593261442 +0200
+++ vdr-1.2.6/device.c	2004-06-06 22:13:57.865031599 +0200
@@ -33,6 +33,7 @@
 cDevice *cDevice::primaryDevice = NULL;
 
 cDevice::cDevice(void)
+  : cThread("cDevice")
 {
   cardIndex = nextCardIndex++;
 
Index: vdr-1.2.6/dvbdevice.c
===================================================================
--- vdr-1.2.6.orig/dvbdevice.c	2004-06-06 22:13:38.597260563 +0200
+++ vdr-1.2.6/dvbdevice.c	2004-06-06 22:13:57.867031161 +0200
@@ -67,6 +67,7 @@
 // --- cDvbTuner -------------------------------------------------------------
 
 cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType, cCiHandler *CiHandler)
+  : cThread("cDvbTuner")
 {
   fd_frontend = Fd_Frontend;
   cardIndex = CardIndex;
@@ -461,6 +462,7 @@
 int cDvbDevice::devVideoOffset = -1;
 
 cDvbDevice::cDvbDevice(int n)
+  : cDevice()
 {
   LOCK_THREAD;
   dvbTuner = NULL;
Index: vdr-1.2.6/lirc.c
===================================================================
--- vdr-1.2.6.orig/lirc.c	2004-06-06 22:13:38.592261661 +0200
+++ vdr-1.2.6/lirc.c	2004-06-06 22:13:57.868030941 +0200
@@ -19,6 +19,7 @@
 
 cLircRemote::cLircRemote(char *DeviceName)
 :cRemote("LIRC")
+  , cThread("cLircRemote")
 {
   struct sockaddr_un addr;
   addr.sun_family = AF_UNIX;
Index: vdr-1.2.6/rcu.c
===================================================================
--- vdr-1.2.6.orig/rcu.c	2004-06-06 22:13:38.587262759 +0200
+++ vdr-1.2.6/rcu.c	2004-06-06 22:13:57.869030722 +0200
@@ -18,6 +18,7 @@
 
 cRcuRemote::cRcuRemote(char *DeviceName)
 :cRemote("RCU")
+  , cThread("cRcuRemote")
 {
   dp = 0;
   mode = modeB;
Index: vdr-1.2.6/recorder.c
===================================================================
--- vdr-1.2.6.orig/recorder.c	2004-06-06 22:13:38.590262100 +0200
+++ vdr-1.2.6/recorder.c	2004-06-06 22:13:57.869030722 +0200
@@ -25,6 +25,7 @@
 
 cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2)
 :cReceiver(Ca, Priority, 5, VPid, APid1, APid2, DPid1, DPid2)
+  , cThread("cRecorder")
 {
   ringBuffer = NULL;
   remux = NULL;
Index: vdr-1.2.6/remote.c
===================================================================
--- vdr-1.2.6.orig/remote.c	2004-06-06 22:13:38.585263198 +0200
+++ vdr-1.2.6/remote.c	2004-06-06 22:13:57.869030722 +0200
@@ -197,6 +197,7 @@
 
 cKbdRemote::cKbdRemote(void)
 :cRemote("KBD")
+  , cThread("cKbdRemote")
 {
   active = false;
   tcgetattr(STDIN_FILENO, &savedTm);
Index: vdr-1.2.6/sections.c
===================================================================
--- vdr-1.2.6.orig/sections.c	2004-06-06 22:13:38.589262320 +0200
+++ vdr-1.2.6/sections.c	2004-06-06 22:13:57.870030503 +0200
@@ -15,6 +15,7 @@
 #define MAX_FILTERS 20
 
 cSectionsScanner::cSectionsScanner(const char *FileName)
+  : cThread("cSectionsScanner")
 {
     fileName = strdup(FileName);
     currentSource = 0;
Index: vdr-1.2.6/thread.c
===================================================================
--- vdr-1.2.6.orig/thread.c	2004-06-06 22:13:38.595261002 +0200
+++ vdr-1.2.6/thread.c	2004-06-06 22:13:57.870030503 +0200
@@ -20,6 +20,11 @@
 
 extern sigset_t TheSigset;	// The signals handled in VDR
 
+#ifdef DEBUG_MUTEX
+static unsigned mtxcnt = 0;
+static pthread_mutex_t mtxcnt_m = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
 // --- cCondVar --------------------------------------------------------------
 
 cCondVar::cCondVar(void)
@@ -89,16 +94,35 @@
   locked = 0;
   pthread_mutexattr_t attr = { PTHREAD_MUTEX_ERRORCHECK_NP };
   pthread_mutex_init(&mutex, &attr);
+#ifdef DEBUG_MUTEX
+  pthread_mutex_lock(&mtxcnt_m);
+  _id = ++mtxcnt;
+  pthread_mutex_unlock(&mtxcnt_m);
+#endif
 }
 
 cMutex::~cMutex()
 {
+#ifdef DEBUG_MUTEX
+  pthread_mutex_lock(&mtxcnt_m);
+  --mtxcnt;
+  pthread_mutex_unlock(&mtxcnt_m);
+#endif
   pthread_mutex_destroy(&mutex);
 }
 
 void cMutex::Lock(void)
 {
+#ifdef DEBUG_MUTEX
+  struct timespec t = { time(0) + 1, 0 };
+  if(pthread_mutex_timedlock(&mutex, &t) == ETIMEDOUT)
+  {
+    dsyslog("Thread %ld timeout locking mutex 0x%X, held by %ld\n", pthread_self(), _id, _locker);
+  }
+  _locker = pthread_self();
+#else
   pthread_mutex_lock(&mutex);
+#endif
   locked++;
 }
 
@@ -108,6 +132,13 @@
     pthread_mutex_unlock(&mutex);
 }
 
+#ifdef DEBUG_MUTEX
+unsigned cMutex::id() const
+{
+  return _id;
+}
+#endif
+
 // --- cRwlock --------------------------------------------------------------
 
 cRwLock::cRwLock(void)
@@ -172,7 +203,11 @@
 
   Thread->childTid = pthread_self();
   if (Thread->description)
+#ifdef DEBUG_MUTEX
+     dsyslog("%s thread started (pid=%d, tid=%ld, mutex=0x%X)", Thread->description, getpid(), Thread->childTid, Thread->mutex.id());
+#else
      dsyslog("%s thread started (pid=%d, tid=%ld)", Thread->description, getpid(), Thread->childTid);
+#endif
   Thread->Action();
   if (Thread->description)
      dsyslog("%s thread ended (pid=%d, tid=%ld)", Thread->description, getpid(), Thread->childTid);
Index: vdr-1.2.6/thread.h
===================================================================
--- vdr-1.2.6.orig/thread.h	2004-06-06 22:13:38.596260783 +0200
+++ vdr-1.2.6/thread.h	2004-06-06 22:13:57.871030284 +0200
@@ -41,11 +41,18 @@
 private:
   pthread_mutex_t mutex;
   int locked;
+#ifdef DEBUG_MUTEX
+  unsigned _id;
+  pthread_t _locker;
+#endif
 public:
   cMutex(void);
   ~cMutex();
   void Lock(void);
   void Unlock(void);
+#ifdef DEBUG_MUTEX
+  unsigned id() const;
+#endif
   };
 
 class cRwLock {
@@ -93,7 +100,7 @@
   virtual void Action(void) = 0;
   void Cancel(int WaitSeconds = 0);
 public:
-  cThread(const char *Description = NULL);
+  cThread(const char *Description);
   virtual ~cThread();
   void SetDescription(const char *Description, ...);
   bool Start(void);
Index: vdr-1.2.6/transfer.c
===================================================================
--- vdr-1.2.6.orig/transfer.c	2004-06-06 22:13:38.585263198 +0200
+++ vdr-1.2.6/transfer.c	2004-06-06 22:13:57.871030284 +0200
@@ -19,6 +19,7 @@
 
 cTransfer::cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2)
 :cReceiver(0, -1, 5, VPid, APid1, APid2, DPid1, DPid2)
+  , cThread("cTransfer")
 {
   ringBuffer = new cRingBufferLinear(VIDEOBUFSIZE, TS_SIZE * 2, true);
   remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2);
Index: vdr-1.2.6/vdr.c
===================================================================
--- vdr-1.2.6.orig/vdr.c	2004-06-06 22:13:38.588262540 +0200
+++ vdr-1.2.6/vdr.c	2004-06-06 22:13:57.872030064 +0200
@@ -136,6 +136,7 @@
 
 static void SignalHandler(int signum)
 {
+  dsyslog("%s:%d (%s) Tid: %ld Sig: %d\n",__FILE__, __LINE__, __FUNCTION__, pthread_self(), signum);
   if (signum != SIGPIPE) {
      Interrupted = signum;
      Interface->Interrupt();
@@ -702,6 +703,7 @@
   bool ForceShutdown = false;
   bool UserShutdown = false;
 
+  dsyslog("entering main loop with tid %ld", pthread_self());
   while (!Interrupted) {
         // Handle emergency exits:
         if (cThread::EmergencyExit()) {

Attachment: pgp00005.pgp
Description: PGP signature


Home | Main Index | Thread Index