summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2001-09-15 13:00:58 +0200
committerKlaus Schmidinger <vdr@tvdr.de>2001-09-15 13:00:58 +0200
commit7913b00daa6c95f4a8fdbc96793dc08f26a5f121 (patch)
tree7f3f93fed911b2380f8f869e1e5617e8cc55bcc7
parent37754870e0868f41549c63941ed4a236751e70e4 (diff)
downloadvdr-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--CONTRIBUTORS6
-rw-r--r--HISTORY5
-rw-r--r--dvbapi.c10
-rw-r--r--thread.c106
-rw-r--r--thread.h18
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)
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 <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)
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 <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;
+}
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 <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