diff options
author | Klaus Schmidinger <vdr@tvdr.de> | 2001-09-15 13:00:58 +0200 |
---|---|---|
committer | Klaus Schmidinger <vdr@tvdr.de> | 2001-09-15 13:00:58 +0200 |
commit | 7913b00daa6c95f4a8fdbc96793dc08f26a5f121 (patch) | |
tree | 7f3f93fed911b2380f8f869e1e5617e8cc55bcc7 | |
parent | 37754870e0868f41549c63941ed4a236751e70e4 (diff) | |
download | vdr-7913b00daa6c95f4a8fdbc96793dc08f26a5f121.tar.gz vdr-7913b00daa6c95f4a8fdbc96793dc08f26a5f121.tar.bz2 |
Pipe to Dolby Digital replay command closes all unused file descriptors to avoid crashing when OSD is on
-rw-r--r-- | CONTRIBUTORS | 6 | ||||
-rw-r--r-- | HISTORY | 5 | ||||
-rw-r--r-- | dvbapi.c | 10 | ||||
-rw-r--r-- | thread.c | 106 | ||||
-rw-r--r-- | thread.h | 18 |
5 files changed, 134 insertions, 11 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS index bf3a39cc..9090ca9f 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -106,7 +106,7 @@ Stefan Huelswitt <huels@iname.com> Ulrich Röder <dynamite@efr-net.de> for pointing out that there are channels that have a symbol rate higher than - 27500. + 27500 Helmut Schächner <schaechner@yahoo.com> for his support in keeping the Premiere World channels up to date in 'channels.conf' @@ -135,3 +135,7 @@ Werner Fink <werner@suse.de> Rolf Hakenes <hakenes@hippomi.de> for providing 'libdtv' and adapting the EIT mechanisms to it + +Andreas Vitting <Andreas@huji.de> + for providing code that closes all unused file descriptors in the child + process of a pipe (used in cPipe) @@ -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). @@ -7,7 +7,7 @@ * DVD support initially written by Andreas Schultz <aschultz@warp10.net> * based on dvdplayer-0.5 by Matjaz Thaler <matjaz.thaler@guest.arnes.si> * - * $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) @@ -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 <errno.h> #include <signal.h> +#include <sys/resource.h> #include <sys/wait.h> #include <unistd.h> #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 <Andreas@huji.de> + +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; +} @@ -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 <pthread.h> +#include <stdio.h> #include <sys/types.h> 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 |