aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/eval.c10
-rw-r--r--src/nvim/event/process.c7
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/main.c3
-rw-r--r--src/nvim/msgpack_rpc/channel.c7
-rw-r--r--src/nvim/msgpack_rpc/remote_ui.c2
-rw-r--r--src/nvim/terminal.c4
-rw-r--r--src/nvim/tui/tui.c2
-rw-r--r--test/functional/job/job_spec.lua36
9 files changed, 60 insertions, 13 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index a5ab57785c..006601211e 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -18987,7 +18987,7 @@ void ex_function(exarg_T *eap)
emsg_funcname(e_funcexts, name);
goto erret;
}
- if (fp->uf_calls > 0) {
+ if (fp->uf_refcount > 1 || fp->uf_calls > 0) {
emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"),
name);
goto erret;
@@ -21136,14 +21136,18 @@ static inline bool common_job_start(TerminalJobData *data, typval_T *rettv)
{
data->refcount++;
Process *proc = (Process *)&data->proc;
+ char *cmd = xstrdup(proc->argv[0]);
if (!process_spawn(proc)) {
- EMSG(_(e_jobexe));
+ EMSG2(_(e_jobspawn), cmd);
+ xfree(cmd);
if (proc->type == kProcessTypePty) {
xfree(data->proc.pty.term_name);
- free_term_job_data(data);
}
+ rettv->vval.v_number = proc->status;
+ term_job_data_decref(data);
return false;
}
+ xfree(cmd);
data->id = current_job_id++;
wstream_init(proc->in, 0);
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index 81d4e690c3..bacbf4f8c7 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -66,7 +66,12 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL
if (proc->err) {
uv_close((uv_handle_t *)&proc->err->uv.pipe, NULL);
}
- process_close(proc);
+
+ if (proc->type == kProcessTypeUv) {
+ uv_close((uv_handle_t *)&(((UvProcess *)proc)->uv), NULL);
+ } else {
+ process_close(proc);
+ }
shell_free_argv(proc->argv);
proc->status = -1;
return false;
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 68cb923e42..5126195841 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -1107,6 +1107,8 @@ EXTERN char_u e_isadir2[] INIT(= N_("E17: \"%s\" is a directory"));
EXTERN char_u e_invjob[] INIT(= N_("E900: Invalid job id"));
EXTERN char_u e_jobtblfull[] INIT(= N_("E901: Job table is full"));
EXTERN char_u e_jobexe[] INIT(= N_("E902: \"%s\" is not an executable"));
+EXTERN char_u e_jobspawn[] INIT(= N_(
+ "E903: Process for command \"%s\" could not be spawned"));
EXTERN char_u e_jobnotpty[] INIT(= N_("E904: Job is not connected to a pty"));
EXTERN char_u e_libcall[] INIT(= N_("E364: Library call failed for \"%s()\""));
EXTERN char_u e_mkdir[] INIT(= N_("E739: Cannot create directory %s: %s"));
diff --git a/src/nvim/main.c b/src/nvim/main.c
index e11db16c61..9af15924bd 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -245,6 +245,7 @@ int main(int argc, char **argv)
set_vim_var_string(VV_PROGPATH, (char_u *)argv[0], -1);
set_vim_var_string(VV_PROGNAME, path_tail((char_u *)argv[0]), -1);
+ event_init();
/*
* Process the command line arguments. File names are put in the global
* argument list "global_alist".
@@ -275,7 +276,6 @@ int main(int argc, char **argv)
if (GARGCOUNT > 1 && !silent_mode)
printf(_("%d files to edit\n"), GARGCOUNT);
- event_init();
full_screen = true;
t_colors = 256;
check_tty(&params);
@@ -963,6 +963,7 @@ static void command_line_scan(mparm_T *parmp)
} else if (STRICMP(argv[0] + argv_idx, "embed") == 0) {
embedded_mode = true;
parmp->headless = true;
+ channel_from_stdio();
} else if (STRNICMP(argv[0] + argv_idx, "literal", 7) == 0) {
#if !defined(UNIX)
parmp->literal = TRUE;
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 0e3b8200c9..d8f86cefab 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -93,11 +93,6 @@ void channel_init(void)
channels = pmap_new(uint64_t)();
event_strings = pmap_new(cstr_t)();
msgpack_sbuffer_init(&out_buffer);
-
- if (embedded_mode) {
- channel_from_stdio();
- }
-
remote_ui_init();
}
@@ -316,7 +311,7 @@ bool channel_close(uint64_t id)
/// Creates an API channel from stdin/stdout. This is used when embedding
/// Neovim
-static void channel_from_stdio(void)
+void channel_from_stdio(void)
{
Channel *channel = register_channel(kChannelTypeStdio);
incref(channel); // stdio channels are only closed on exit
diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c
index 403ac13f2f..f0d92b52a0 100644
--- a/src/nvim/msgpack_rpc/remote_ui.c
+++ b/src/nvim/msgpack_rpc/remote_ui.c
@@ -28,7 +28,7 @@ void remote_ui_init(void)
connected_uis = pmap_new(uint64_t)();
// Add handler for "attach_ui"
String method = cstr_as_string("ui_attach");
- MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .async = true};
+ MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .async = false};
msgpack_rpc_add_method_handler(method, handler);
method = cstr_as_string("ui_detach");
handler.fn = remote_ui_detach;
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index eb010bc190..931105717b 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -423,7 +423,9 @@ end:
ui_busy_stop();
if (close) {
term->opts.close_cb(term->opts.data);
- do_cmdline_cmd("bwipeout!");
+ if (term->buf) {
+ do_cmdline_cmd("bwipeout!");
+ }
}
}
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 6382993d5b..acc2ccc682 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -140,6 +140,7 @@ UI *tui_start(void)
// listen for SIGWINCH
signal_watcher_init(&loop, &data->winch_handle, ui);
+ data->winch_handle.events = queue_new_child(loop.events);
signal_watcher_start(&data->winch_handle, sigwinch_cb, SIGWINCH);
ui->stop = tui_stop;
@@ -179,6 +180,7 @@ static void tui_stop(UI *ui)
// Destroy common stuff
kv_destroy(data->invalid_regions);
signal_watcher_stop(&data->winch_handle);
+ queue_free(data->winch_handle.events);
signal_watcher_close(&data->winch_handle, NULL);
// Destroy input stuff
term_input_destroy(data->input);
diff --git a/test/functional/job/job_spec.lua b/test/functional/job/job_spec.lua
index 7085d61cc7..bdaf2a7ec6 100644
--- a/test/functional/job/job_spec.lua
+++ b/test/functional/job/job_spec.lua
@@ -6,6 +6,7 @@ local clear, eq, eval, execute, expect, feed, insert, neq, next_msg, nvim,
helpers.insert, helpers.neq, helpers.next_message, helpers.nvim,
helpers.nvim_dir, helpers.ok, helpers.run, helpers.session, helpers.source,
helpers.stop, helpers.wait, helpers.write_file
+local Screen = require('test.functional.ui.screen')
describe('jobs', function()
@@ -188,6 +189,41 @@ describe('jobs', function()
eq({'notification', 'exit', {45, 10}}, next_msg())
end)
+ it('cant redefine callbacks being used by a job', function()
+ local screen = Screen.new()
+ screen:attach()
+ local script = [[
+ function! g:JobHandler(job_id, data, event)
+ endfunction
+
+ let g:callbacks = {
+ \ 'on_stdout': function('g:JobHandler'),
+ \ 'on_stderr': function('g:JobHandler'),
+ \ 'on_exit': function('g:JobHandler')
+ \ }
+ let job = jobstart('cat -', g:callbacks)
+ ]]
+ source(script)
+ feed(':function! g:JobHandler(job_id, data, event)<cr>')
+ feed(':endfunction<cr>')
+ screen:expect([[
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ :function! g:JobHandler(job_id, data, event) |
+ : :endfunction |
+ E127: Cannot redefine function JobHandler: It is in u|
+ se |
+ Press ENTER or type command to continue^ |
+ ]])
+ end)
+
describe('jobwait', function()
it('returns a list of status codes', function()
source([[