summaryrefslogtreecommitdiff
path: root/thread.c
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 /thread.c
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
Diffstat (limited to 'thread.c')
-rw-r--r--thread.c106
1 files changed, 105 insertions, 1 deletions
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;
+}