diff --git a/src/main.c b/src/main.c index c3fd56b4..b98fdcca 100644 --- a/src/main.c +++ b/src/main.c @@ -795,6 +795,8 @@ main(int argc, char **argv) * Initialize subsystems */ + spawn_init(); + dbus_server_init(opt_dbus, opt_dbus_session); intlconv_init(); @@ -943,6 +945,7 @@ main(int argc, char **argv) tvhftrace("main", intlconv_done); tvhftrace("main", urlparse_done); tvhftrace("main", idnode_done); + tvhftrace("main", spawn_done); tvhlog(LOG_NOTICE, "STOP", "Exiting HTS Tvheadend"); tvhlog_end(); diff --git a/src/spawn.c b/src/spawn.c index f3530b34..a6748ea3 100644 --- a/src/spawn.c +++ b/src/spawn.c @@ -43,12 +43,87 @@ pthread_mutex_t spawn_mutex = PTHREAD_MUTEX_INITIALIZER; static LIST_HEAD(, spawn) spawns; +static char *spawn_info_buf = NULL; +static char *spawn_error_buf = NULL; + +static th_pipe_t spawn_pipe_info; +static th_pipe_t spawn_pipe_error; + typedef struct spawn { LIST_ENTRY(spawn) link; pid_t pid; const char *name; } spawn_t; +/* + * + */ +#define SPAWN_PIPE_READ_SIZE 4096 + +static void +spawn_pipe_read( th_pipe_t *p, char **_buf, int level ) +{ + char *buf = *_buf, *s; + size_t len; + int r; + + if (buf == NULL) { + buf = malloc(SPAWN_PIPE_READ_SIZE); + buf[0] = '\0'; + buf[SPAWN_PIPE_READ_SIZE - 1] = 0; + *_buf = buf; + } + while (1) { + len = strlen(buf); + r = read(p->rd, buf + len, SPAWN_PIPE_READ_SIZE - 1 - len); + if (r < 1) { + if (errno == EAGAIN) + break; + if (ERRNO_AGAIN(errno)) + continue; + break; + } + while ((s = strchr(buf, '\n')) != NULL) { + *s++ = '\0'; + tvhlog(level, "spawn", "%s", buf); + memmove(buf, s, strlen(s) + 1); + } + if (strlen(buf) == SPAWN_PIPE_READ_SIZE - 1) { + tvherror("spawn", "pipe buffer full"); + buf[0] = '\0'; + } + } +} + +static void +spawn_pipe_write( th_pipe_t *p, const char *fmt, va_list ap ) +{ + char buf[512]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + write(p->wr, buf, strlen(buf)); +} + +void +spawn_info( const char *fmt, ... ) +{ + va_list ap; + + va_start(ap, fmt); + spawn_pipe_write(&spawn_pipe_info, fmt, ap); + va_end(ap); +} + +void +spawn_error( const char *fmt, ... ) +{ + va_list ap; + + va_start(ap, fmt); + spawn_pipe_write(&spawn_pipe_error, fmt, ap); + va_end(ap); +} + /* * Search PATH for executable */ @@ -93,6 +168,9 @@ spawn_reap(char *stxt, size_t stxtlen) int status, res; spawn_t *s; + spawn_pipe_read(&spawn_pipe_info, &spawn_info_buf, LOG_INFO); + spawn_pipe_read(&spawn_pipe_error, &spawn_error_buf, LOG_ERR); + pid = waitpid(-1, &status, WNOHANG); if(pid < 1) return -EAGAIN; @@ -206,9 +284,8 @@ spawn_and_store_stdout(const char *prog, char *argv[], char **outp) f = open("/dev/null", O_RDWR); if(f == -1) { - syslog(LOG_ERR, - "spawn: pid %d cannot open /dev/null for redirect %s -- %s", - getpid(), prog, strerror(errno)); + spawn_error("pid %d cannot open /dev/null for redirect %s -- %s", + getpid(), prog, strerror(errno)); exit(1); } @@ -216,9 +293,11 @@ spawn_and_store_stdout(const char *prog, char *argv[], char **outp) dup2(f, 2); close(f); + spawn_info("Executing \"%s\"\n", prog); + execve(prog, argv, environ); - syslog(LOG_ERR, "spawn: pid %d cannot execute %s -- %s", - getpid(), prog, strerror(errno)); + spawn_error("pid %d cannot execute %s -- %s\n", + getpid(), prog, strerror(errno)); exit(1); } @@ -264,10 +343,10 @@ spawnv(const char *prog, char *argv[]) if(p == 0) { close(0); close(2); - syslog(LOG_INFO, "spawn: Executing \"%s\"", prog); + spawn_info("Executing \"%s\"\n", prog); execve(prog, argv, environ); - syslog(LOG_ERR, "spawn: pid %d cannot execute %s -- %s", - getpid(), prog, strerror(errno)); + spawn_error("pid %d cannot execute %s -- %s\n", + getpid(), prog, strerror(errno)); close(1); exit(1); } @@ -275,3 +354,20 @@ spawnv(const char *prog, char *argv[]) spawn_enq(prog, p); return 0; } + +/* + * + */ +void spawn_init(void) +{ + tvh_pipe(O_NONBLOCK, &spawn_pipe_info); + tvh_pipe(O_NONBLOCK, &spawn_pipe_error); +} + +void spawn_done(void) +{ + tvh_pipe_close(&spawn_pipe_error); + tvh_pipe_close(&spawn_pipe_info); + free(spawn_error_buf); + free(spawn_info_buf); +} diff --git a/src/spawn.h b/src/spawn.h index 64e734bf..36ae3226 100644 --- a/src/spawn.h +++ b/src/spawn.h @@ -19,6 +19,10 @@ #ifndef SPAWN_H #define SPAWN_H +void spawn_info ( const char *fmt, ... ); + +void spawn_error ( const char *fmt, ... ); + int find_exec ( const char *name, char *out, size_t len ); int spawn_and_store_stdout(const char *prog, char *argv[], char **outp); @@ -29,4 +33,8 @@ int spawn_reap(char *stxt, size_t stxtlen); void spawn_reaper(void); +void spawn_init(void); + +void spawn_done(void); + #endif /* SPAWN_H */