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