diff --git a/CONTRIBUTORS b/CONTRIBUTORS index bf3a39cc..9090ca9f 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -106,7 +106,7 @@ Stefan Huelswitt Ulrich Röder for pointing out that there are channels that have a symbol rate higher than - 27500. + 27500 Helmut Schächner for his support in keeping the Premiere World channels up to date in 'channels.conf' @@ -135,3 +135,7 @@ Werner Fink Rolf Hakenes for providing 'libdtv' and adapting the EIT mechanisms to it + +Andreas Vitting + for providing code that closes all unused file descriptors in the child + process of a pipe (used in cPipe) diff --git a/HISTORY b/HISTORY index 4cf03d27..9ad19127 100644 --- a/HISTORY +++ b/HISTORY @@ -716,7 +716,7 @@ Video Disk Recorder Revision History That way every recording will store the actual summary data at the time of the recording. -2001-09-14: Version 0.95 +2001-09-15: Version 0.95 - Fixed behaviour in case the shutdown didn't take place (there were many "next timer event at..." messages in that case). @@ -742,3 +742,6 @@ Video Disk Recorder Revision History - Changed the size of all input buffers used to parse config files or receive SVDRP commands to the same value of 10KB. This allows long strings to be used in the 'summary' field of a timer, for instance. +- The pipe to the Dolby Digital replay command (option '-a') now closes all + unused file descriptors in the child process to avoid crashing when the + OSD is used (thanks to Andreas Vitting). diff --git a/dvbapi.c b/dvbapi.c index 07999a01..829bc701 100644 --- a/dvbapi.c +++ b/dvbapi.c @@ -7,7 +7,7 @@ * DVD support initially written by Andreas Schultz * based on dvdplayer-0.5 by Matjaz Thaler * - * $Id: dvbapi.c 1.118 2001/09/15 10:42:35 kls Exp $ + * $Id: dvbapi.c 1.119 2001/09/15 12:45:19 kls Exp $ */ //#define DVDDEBUG 1 @@ -693,7 +693,7 @@ protected: static int Speeds[]; cDvbApi *dvbApi; int videoDev, audioDev; - FILE *dolbyDev; + cPipe dolbyDev; int blockInput, blockOutput; ePlayModes playMode; ePlayDirs playDir; @@ -733,7 +733,6 @@ cPlayBuffer::cPlayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev) dvbApi = DvbApi; videoDev = VideoDev; audioDev = AudioDev; - dolbyDev = NULL; blockInput = blockOutput = false; playMode = pmPlay; playDir = pdForward; @@ -743,16 +742,13 @@ cPlayBuffer::cPlayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev) canToggleAudioTrack = false; audioTrack = 0xC0; if (cDvbApi::AudioCommand()) { - dolbyDev = popen(cDvbApi::AudioCommand(), "w"); - if (!dolbyDev) + if (!dolbyDev.Open(cDvbApi::AudioCommand(), "w")) esyslog(LOG_ERR, "ERROR: can't open pipe to audio command '%s'", cDvbApi::AudioCommand()); } } cPlayBuffer::~cPlayBuffer() { - if (dolbyDev) - pclose(dolbyDev); } void cPlayBuffer::Output(void) diff --git a/thread.c b/thread.c index bfc8aab1..ec66440e 100644 --- a/thread.c +++ b/thread.c @@ -4,12 +4,13 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: thread.c 1.11 2001/08/05 10:36:52 kls Exp $ + * $Id: thread.c 1.12 2001/09/15 13:00:58 kls Exp $ */ #include "thread.h" #include #include +#include #include #include #include "tools.h" @@ -235,3 +236,106 @@ bool cThreadLock::Locked(void) return locked; } +// --- cPipe ----------------------------------------------------------------- + +// cPipe::Open() and cPipe::Close() are based on code originally received from +// Andreas Vitting + +cPipe::cPipe(void) +{ + pid = -1; + f = NULL; +} + +cPipe::~cPipe() +{ + Close(); +} + +bool cPipe::Open(const char *Command, const char *Mode) +{ + int fd[2]; + + if (pipe(fd) < 0) { + LOG_ERROR; + return false; + } + if ((pid = fork()) < 0) { // fork failed + LOG_ERROR; + close(fd[0]); + close(fd[1]); + return false; + } + + char *mode = "w"; + int iopipe = 0; + + if (pid > 0) { // parent process + if (strcmp(Mode, "r") == 0) { + mode = "r"; + iopipe = 1; + } + close(fd[iopipe]); + f = fdopen(fd[1 - iopipe], mode); + if ((f = fdopen(fd[1 - iopipe], mode)) == NULL) { + LOG_ERROR; + close(fd[1 - iopipe]); + } + return f != NULL; + } + else { // child process + int iofd = STDOUT_FILENO; + if (strcmp(Mode, "w") == 0) { + mode = "r"; + iopipe = 1; + iofd = STDIN_FILENO; + } + close(fd[iopipe]); + if (dup2(fd[1 - iopipe], iofd) == -1) { // now redirect + LOG_ERROR; + close(fd[1 - iopipe]); + _exit(-1); + } + else { + for (int i = STDERR_FILENO + 1; i < fd[1 - iopipe]; i++) + close(i); //close all dup'ed filedescriptors + if (execl("/bin/sh", "sh", "-c", Command, NULL) == -1) { + LOG_ERROR_STR(Command); + close(fd[1 - iopipe]); + _exit(-1); + } + } + _exit(0); + } +} + +int cPipe::Close(void) +{ + int ret = -1; + + if (f) { + fclose(f); + f = NULL; + } + + if (pid >= 0) { + int status = 0; + struct rusage ru; + int i = 5; + while (ret == -1 && i > 0) { + usleep(1000); + ret = wait4(pid, &status, WNOHANG, &ru); + i--; + } + + if (!i) { + kill(pid, SIGKILL); + ret = -1; + } + else if (ret == -1 || !WIFEXITED(status)) + ret = -1; + pid = -1; + } + + return ret; +} diff --git a/thread.h b/thread.h index e8e796eb..221f9ac7 100644 --- a/thread.h +++ b/thread.h @@ -4,13 +4,14 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: thread.h 1.8 2001/08/05 10:36:47 kls Exp $ + * $Id: thread.h 1.9 2001/09/15 12:46:52 kls Exp $ */ #ifndef __THREAD_H #define __THREAD_H #include +#include #include class cMutex; @@ -88,4 +89,19 @@ public: #define LOCK_THREAD cThreadLock ThreadLock(this) +// cPipe implements a pipe that closes all unnecessary file descriptors in +// the child process. + +class cPipe { +private: + pid_t pid; + FILE *f; +public: + cPipe(void); + ~cPipe(); + operator FILE* () { return f; } + bool Open(const char *Command, const char *Mode); + int Close(void); + }; + #endif //__THREAD_H