aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/vim.c33
-rw-r--r--src/nvim/channel.c17
-rw-r--r--src/nvim/event/process.c20
-rw-r--r--src/nvim/event/process.h1
4 files changed, 50 insertions, 21 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 2536249de5..5f48a26a29 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -2057,27 +2057,28 @@ void nvim_set_client_info(uint64_t channel_id, String name,
rpc_set_client_info(channel_id, info);
}
-/// Get information about a channel.
+/// Gets information about a channel.
///
/// @returns Dictionary describing a channel, with these keys:
-/// - "stream" the stream underlying the channel
+/// - "id" Channel id.
+/// - "argv" (optional) Job arguments list.
+/// - "stream" Stream underlying the channel.
/// - "stdio" stdin and stdout of this Nvim instance
/// - "stderr" stderr of this Nvim instance
/// - "socket" TCP/IP socket or named pipe
-/// - "job" job with communication over its stdio
-/// - "mode" how data received on the channel is interpreted
-/// - "bytes" send and receive raw bytes
-/// - "terminal" a |terminal| instance interprets ASCII sequences
-/// - "rpc" |RPC| communication on the channel is active
-/// - "pty" Name of pseudoterminal, if one is used (optional).
-/// On a POSIX system, this will be a device path like
-/// /dev/pts/1. Even if the name is unknown, the key will
-/// still be present to indicate a pty is used. This is
-/// currently the case when using winpty on windows.
-/// - "buffer" buffer with connected |terminal| instance (optional)
-/// - "client" information about the client on the other end of the
-/// RPC channel, if it has added it using
-/// |nvim_set_client_info()|. (optional)
+/// - "job" Job with communication over its stdio.
+/// - "mode" How data received on the channel is interpreted.
+/// - "bytes" Send and receive raw bytes.
+/// - "terminal" |terminal| instance interprets ASCII sequences.
+/// - "rpc" |RPC| communication on the channel is active.
+/// - "pty" (optional) Name of pseudoterminal. On a POSIX system this
+/// is a device path like "/dev/pts/1". If the name is unknown,
+/// the key will still be present if a pty is used (e.g. for
+/// winpty on Windows).
+/// - "buffer" (optional) Buffer with connected |terminal| instance.
+/// - "client" (optional) Info about the peer (client on the other end of
+/// the RPC channel), if provided by it via
+/// |nvim_set_client_info()|.
///
Dictionary nvim_get_chan_info(Integer chan, Error *err)
FUNC_API_SINCE(4)
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index 6f12d2eab8..94db7fb3b9 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -240,6 +240,10 @@ static void free_channel_event(void **argv)
rpc_free(chan);
}
+ if (chan->streamtype == kChannelStreamProc) {
+ process_free(&chan->stream.proc);
+ }
+
callback_reader_free(&chan->on_data);
callback_reader_free(&chan->on_stderr);
callback_free(&chan->on_exit);
@@ -847,13 +851,24 @@ Dictionary channel_info(uint64_t id)
const char *stream_desc, *mode_desc;
switch (chan->streamtype) {
- case kChannelStreamProc:
+ case kChannelStreamProc: {
stream_desc = "job";
if (chan->stream.proc.type == kProcessTypePty) {
const char *name = pty_process_tty_name(&chan->stream.pty);
PUT(info, "pty", STRING_OBJ(cstr_to_string(name)));
}
+
+ char **p = chan->stream.proc.argv;
+ Array argv = ARRAY_DICT_INIT;
+ if (p != NULL) {
+ while (*p != NULL) {
+ ADD(argv, STRING_OBJ(cstr_to_string(*p)));
+ p++;
+ }
+ }
+ PUT(info, "argv", ARRAY_OBJ(argv));
break;
+ }
case kChannelStreamStdio:
stream_desc = "stdio";
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index a2aafc94c8..8b366d0f3c 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -88,7 +88,7 @@ int process_spawn(Process *proc, bool in, bool out, bool err)
} else {
process_close(proc);
}
- shell_free_argv(proc->argv);
+ process_free(proc);
proc->status = -1;
return status;
}
@@ -201,7 +201,7 @@ int process_wait(Process *proc, int ms, MultiQueue *events)
// Job exited, free its resources.
decref(proc);
if (proc->events) {
- // the decref call created an exit event, process it now
+ // decref() created an exit event, process it now.
multiqueue_process_events(proc->events);
}
} else {
@@ -239,6 +239,15 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
KILL_TIMEOUT_MS, 0);
}
+// Frees process-owned resources.
+void process_free(Process *proc) FUNC_ATTR_NONNULL_ALL
+{
+ if (proc->argv != NULL) {
+ shell_free_argv(proc->argv);
+ proc->argv = NULL;
+ }
+}
+
/// Sends SIGKILL (or SIGTERM..SIGKILL for PTY jobs) to processes that did
/// not terminate after process_stop().
static void children_kill_cb(uv_timer_t *handle)
@@ -269,9 +278,12 @@ static void children_kill_cb(uv_timer_t *handle)
static void process_close_event(void **argv)
{
Process *proc = argv[0];
- shell_free_argv(proc->argv);
- if (proc->cb) { // "on_exit" for jobstart(). See channel_job_start().
+ if (proc->cb) {
+ // User (hint: channel_job_start) is responsible for calling
+ // process_free().
proc->cb(proc, proc->status, proc->data);
+ } else {
+ process_free(proc);
}
}
diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h
index 24debdb276..20c02e4900 100644
--- a/src/nvim/event/process.h
+++ b/src/nvim/event/process.h
@@ -26,6 +26,7 @@ struct process {
char **argv;
dict_T *env;
Stream in, out, err;
+ /// Exit handler. If set, user must call process_free().
process_exit_cb cb;
internal_process_cb internal_exit_cb, internal_close_cb;
bool closed, detach, overlapped;