summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-02-16 23:09:30 +0100
committerwm4 <wm4@nowhere>2020-02-16 23:09:30 +0100
commite0f85553c043fc18dc7f97dd74f2e0da8cf7bc14 (patch)
tree928d4f1a42807e8663e9f6bed29ad7dbcf224d85
parent249bb091d4880a564c00f8354111e12cfd0183a3 (diff)
downloadmpv-e0f85553c043fc18dc7f97dd74f2e0da8cf7bc14.tar.bz2
mpv-e0f85553c043fc18dc7f97dd74f2e0da8cf7bc14.tar.xz
linux pidfd_open testpidfd_test
Seems to work. Syscall wrapper copy&pasted from the manpage.
-rw-r--r--osdep/subprocess-posix.c50
-rw-r--r--player/lua/ytdl_hook.lua17
2 files changed, 62 insertions, 5 deletions
diff --git a/osdep/subprocess-posix.c b/osdep/subprocess-posix.c
index fb11179618..395186d962 100644
--- a/osdep/subprocess-posix.c
+++ b/osdep/subprocess-posix.c
@@ -32,6 +32,23 @@
#include "osdep/io.h"
#include "stream/stream.h"
+ #include <sys/syscall.h>
+ #include <unistd.h>
+ #include <poll.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+
+ #ifndef __NR_pidfd_open
+ #define __NR_pidfd_open 434 /* System call # on most architectures */
+ #endif
+
+ static int
+ pidfd_open(pid_t pid, unsigned int flags)
+ {
+ return syscall(__NR_pidfd_open, pid, flags);
+ }
+
+
extern char **environ;
#define SAFE_CLOSE(fd) do { if ((fd) >= 0) close((fd)); (fd) = -1; } while (0)
@@ -48,6 +65,7 @@ void mp_subprocess2(struct mp_subprocess_opts *opts,
bool spawned = false;
bool killed_by_us = false;
int cancel_fd = -1;
+ int pid_fd = -1;
*res = (struct mp_subprocess_result){0};
@@ -119,9 +137,12 @@ void mp_subprocess2(struct mp_subprocess_opts *opts,
SAFE_CLOSE(comm_pipe[n][1]);
SAFE_CLOSE(devnull);
+ if (pid)
+ pid_fd = pidfd_open(pid, 0);
+
while (1) {
- struct pollfd fds[MP_SUBPROCESS_MAX_FDS + 1];
- int map_fds[MP_SUBPROCESS_MAX_FDS + 1];
+ struct pollfd fds[MP_SUBPROCESS_MAX_FDS + 2];
+ int map_fds[MP_SUBPROCESS_MAX_FDS + 2];
int num_fds = 0;
for (int n = 0; n < opts->num_fds; n++) {
if (comm_pipe[n][0] >= 0) {
@@ -132,8 +153,15 @@ void mp_subprocess2(struct mp_subprocess_opts *opts,
};
}
}
+
+ if (pid_fd >= 0) {
+ map_fds[num_fds] = -2;
+ fds[num_fds++] = (struct pollfd){.events = POLLIN, .fd = pid_fd};
+ }
+
if (!num_fds)
break;
+
if (cancel_fd >= 0) {
map_fds[num_fds] = -1;
fds[num_fds++] = (struct pollfd){.events = POLLIN, .fd = cancel_fd};
@@ -145,12 +173,17 @@ void mp_subprocess2(struct mp_subprocess_opts *opts,
for (int idx = 0; idx < num_fds; idx++) {
if (fds[idx].revents) {
int n = map_fds[idx];
- if (n < 0) {
+ if (n == -1) {
// cancel_fd
if (pid)
kill(pid, SIGKILL);
killed_by_us = true;
break;
+ } else if (n == -2) {
+ // pid_fd
+ // ignore until all pipes are read fully
+ SAFE_CLOSE(pid_fd);
+ printf("notify close\n");
} else {
char buf[4096];
ssize_t r = read(comm_pipe[n][0], buf, sizeof(buf));
@@ -158,8 +191,10 @@ void mp_subprocess2(struct mp_subprocess_opts *opts,
continue;
if (r > 0 && opts->fds[n].on_read)
opts->fds[n].on_read(opts->fds[n].on_read_ctx, buf, r);
- if (r <= 0)
+ if (r <= 0) {
+ printf("close %d \n", n);
SAFE_CLOSE(comm_pipe[n][0]);
+ }
}
}
}
@@ -170,8 +205,12 @@ void mp_subprocess2(struct mp_subprocess_opts *opts,
// a separate thread and use pthread_cancel(), or use other weird
// and laborious tricks in order to react to mp_cancel.
// So this isn't handled yet.
- if (pid)
+ // Unless pidfd_open() is available.
+ if (pid) {
+ printf("waitpid start\n");
while (waitpid(pid, &status, 0) < 0 && errno == EINTR) {}
+ printf("waitpid done\n");
+ }
done:
if (fa_destroy)
@@ -181,6 +220,7 @@ done:
SAFE_CLOSE(comm_pipe[n][1]);
}
SAFE_CLOSE(devnull);
+ SAFE_CLOSE(pid_fd);
if (!spawned || (pid && WIFEXITED(status) && WEXITSTATUS(status) == 127)) {
res->error = MP_SUBPROCESS_EINIT;
diff --git a/player/lua/ytdl_hook.lua b/player/lua/ytdl_hook.lua
index 8822299671..e489c4edcb 100644
--- a/player/lua/ytdl_hook.lua
+++ b/player/lua/ytdl_hook.lua
@@ -743,3 +743,20 @@ mp.add_hook("on_preloaded", 10, function ()
chapter_list = {}
end
end)
+
+mp.add_forced_key_binding("a", function()
+ print("starting")
+ local ret = mp.command_native_async(
+ {name = "subprocess", args = {"/tmp/test/pid_test"},
+ capture_stdout = true,
+ capture_stderr = true},
+ function(ok, res)
+ print("done " .. utils.format_table(res))
+ end)
+ print("started")
+ -- kill it after some time
+ mp.add_timeout(20, function()
+ print("killing it")
+ mp.abort_async_command(ret)
+ end)
+end) \ No newline at end of file