aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/input.rst1
-rw-r--r--common/msg.c5
-rw-r--r--common/msg_control.h3
-rw-r--r--player/command.c57
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;
}