summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-01-01 20:37:49 +0100
committerDiogo Franco (Kovensky) <diogomfranco@gmail.com>2015-01-25 17:00:16 +0900
commit5c1c8b5fab11054d29bd78a69eb5d3b568288b28 (patch)
tree3e5524b25955f4c531c609e168b007eef5cc4378
parent85f54ce5d0d5d1733bb2029ed43bcbd2bac3e22b (diff)
downloadmpv-5c1c8b5fab11054d29bd78a69eb5d3b568288b28.tar.bz2
mpv-5c1c8b5fab11054d29bd78a69eb5d3b568288b28.tar.xz
command: make the "run" command work on Windows too
Do so by using mp_subprocess(). Although this uses completely different code on Unix too, you shouldn't notice a difference. A less ncie thing is that this reserves an entire thread while the command is running (which wastes some memory for stack, at least). But this is probably still the simplest way, and the fork() trick is apparently not implementable with posix_subprocess(). Conflicts: player/command.c
-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 b3a27b50f7..45273153a4 100644
--- a/DOCS/man/input.rst
+++ b/DOCS/man/input.rst
@@ -240,7 +240,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 bd63746669..ddf4768a11 100644
--- a/player/command.c
+++ b/player/command.c
@@ -63,11 +63,9 @@
#if HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
-#ifndef __MINGW32__
-#include <sys/wait.h>
-#endif
#include "osdep/io.h"
+#include "osdep/subprocess.h"
#include "core.h"
@@ -3841,6 +3839,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;
@@ -4405,28 +4436,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;
}