diff options
-rw-r--r-- | DOCS/man/input.rst | 1 | ||||
-rw-r--r-- | common/msg.c | 5 | ||||
-rw-r--r-- | common/msg_control.h | 3 | ||||
-rw-r--r-- | player/command.c | 57 |
4 files changed, 40 insertions, 26 deletions
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index aed7251aca..1a829c152c 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -249,7 +249,6 @@ List of Input Commands will have after moving.) ``run "command" "arg1" "arg2" ...`` - (Unix only) Run the given command. Unlike in MPlayer/mplayer2 and earlier versions of mpv (0.2.x and older), this doesn't call the shell. Instead, the command is run directly, with each argument passed separately. Each argument is diff --git a/common/msg.c b/common/msg.c index 4a4ad80884..e117589873 100644 --- a/common/msg.c +++ b/common/msg.c @@ -185,10 +185,11 @@ static void flush_status_line(struct mp_log_root *root) root->blank_lines = 0; } -void mp_msg_flush_status_line(struct mpv_global *global) +void mp_msg_flush_status_line(struct mp_log *log) { pthread_mutex_lock(&mp_msg_lock); - flush_status_line(global->log->root); + if (log->root) + flush_status_line(log->root); pthread_mutex_unlock(&mp_msg_lock); } diff --git a/common/msg_control.h b/common/msg_control.h index b0ceef01df..57a7d85368 100644 --- a/common/msg_control.h +++ b/common/msg_control.h @@ -9,9 +9,10 @@ void mp_msg_uninit(struct mpv_global *global); void mp_msg_update_msglevels(struct mpv_global *global); void mp_msg_mute(struct mpv_global *global, bool mute); void mp_msg_force_stderr(struct mpv_global *global, bool force_stderr); -void mp_msg_flush_status_line(struct mpv_global *global); bool mp_msg_has_status_line(struct mpv_global *global); +void mp_msg_flush_status_line(struct mp_log *log); + struct mp_log_buffer_entry { char *prefix; int level; diff --git a/player/command.c b/player/command.c index 1739da76cb..9fb7c82c1c 100644 --- a/player/command.c +++ b/player/command.c @@ -60,11 +60,9 @@ #include "audio/decode/dec_audio.h" #include "options/path.h" #include "screenshot.h" -#ifndef __MINGW32__ -#include <sys/wait.h> -#endif #include "osdep/io.h" +#include "osdep/subprocess.h" #include "core.h" @@ -3920,6 +3918,39 @@ static void overlay_uninit(struct MPContext *mpctx) osd_set_external2(mpctx->osd, NULL); } +struct subprocess_args { + struct mp_log *log; + char **args; +}; + +static void *run_subprocess(void *ptr) +{ + struct subprocess_args *p = ptr; + pthread_detach(pthread_self()); + + mp_msg_flush_status_line(p->log); + + char *err = NULL; + if (mp_subprocess(p->args, NULL, NULL, NULL, NULL, &err) < 0) + mp_err(p->log, "Running subprocess failed: %s\n", err); + + talloc_free(p); + return NULL; +} + +static void subprocess_detached(struct mp_log *log, char **args) +{ + struct subprocess_args *p = talloc_zero(NULL, struct subprocess_args); + p->log = mp_log_new(p, log, NULL); + int num_args = 0; + for (int n = 0; args[n]; n++) + MP_TARRAY_APPEND(p, p->args, num_args, talloc_strdup(p, args[n])); + MP_TARRAY_APPEND(p, p->args, num_args, NULL); + pthread_t thread; + if (pthread_create(&thread, NULL, run_subprocess, p)) + talloc_free(p); +} + struct cycle_counter { char **args; int counter; @@ -4489,28 +4520,10 @@ int run_command(MPContext *mpctx, mp_cmd_t *cmd) break; case MP_CMD_RUN: { -#ifndef __MINGW32__ - mp_msg_flush_status_line(mpctx->global); char *args[MP_CMD_MAX_ARGS + 1] = {0}; for (int n = 0; n < cmd->nargs; n++) args[n] = cmd->args[n].v.s; - pid_t child = fork(); - if (child == 0) { - // Fork twice; the second process will be made child of pid 1 as - // soon as the first process exists, and we don't have to care - // about having to wait for the second process to terminate. - if (fork() == 0) { - execvp(args[0], args); - // mp_msg() is not safe to be called from a forked process. - char s[] = "Executing program failed.\n"; - write(2, s, sizeof(s) - 1); - _exit(1); - } - _exit(0); - } - int st; - while (child != -1 && waitpid(child, &st, 0) < 0 && errno == EINTR) {} -#endif + subprocess_detached(mpctx->log, args); break; } |