-
-
Notifications
You must be signed in to change notification settings - Fork 6k
[RFC] Reimplement job control patch with libuv #475
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Great to see the new plugin architecture taking form! 🎉 |
uv_close((uv_handle_t *)&job->proc_stderr, NULL); | ||
shell_free_argv(job->proc_opts.args); | ||
free(job); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the process watcher is not closed.
Couldn't wait, so I just tested it. It almost works :) In case it's of any value, I get Create a simple bash script:
Do the following in nvim:
|
@justinmk this last commit should have fixed it. Here's something else you can use to play with it:
Open another terminal and type the following:
and start entering lines. Also calling Note that I'm still not handling the redraw issue correctly, for now it's simply calling |
/// @param data Caller data that will be associated with the job | ||
/// @param cb Callback that will be invoked everytime data is available in | ||
/// the job's stdout/stderr | ||
/// @return The job id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
job_start
can fail. Returns 0
in case of error.
I'm curious, is there some "rule" against usage of I think this is something we might want to establish in our code style, as I said I'm ok with gotos for cleanup code. |
@tarruda The dogmatism surrounding anti-goto sentiment is cargo-cult adherence to Dijktra's famous "goto considered harmful" essay. It's still the right tool for C occasionally. The essay was originally written in the context of trying to convince assembly programmers of the 1970s that function dispatch was not going to kill performance.
Exactly. In languages with private functions (and no forward declaration requirement) and RAII or garbage collection, |
@justinmk thanks for the link, interesting read :) |
I'm not satisfied with having to call Some may be wondering why I'm using job ids instead of opaque pointers(could have made the fields of I think this is ready for review, but I will only merge it after #476 . After this is merged I can implement the msgpack API hopefully we'll be able to use python plugins. |
@tarruda Playing around with netcat worked beautifully. One question so far: there doesn't seem to be any protection from overwriting an existing job with the same job name:
For a plugin to avoid collisions like this, it would be useful if |
@justinmk they won't overwrite each other, I think what happened is that the second call to netcat failed because it tried listening on the same port as the first. When you pass a name to jobstart you are actually saying to Neovim: 'When that job sends you some data, emit an 'event' with that name'. This is similar to the event emitter pattern in javascript, except that I tried to use the autocommand infrastructure for it. You can also listen for a namespace of events like this: :let srv1_id = jobstart('netcat-server-1', 'nc', ['-l', '9991'])
:let srv2_id = jobstart('netcat-server-2', 'nc', ['-l', '9992'])
au JobActivity netcat-server-* call append(line('$'), 'message from server '.v:job_data[0].': '. v:job_data[1]) |
From a user interface perspective, I think the design works well, so far. |
There's still some things missing:
But I think it's better to worry about those after the plugin infrastructure is implemented because there might still be some modifications to the job module. |
Rebased/squashed, if no one objects in one hour I will merge it |
@@ -1009,6 +1009,9 @@ EXTERN size_t (*iconv)(iconv_t cd, const char **inbuf, size_t *inbytesleft, | |||
EXTERN char_u e_invrange[] INIT(= N_("E16: Invalid range")); | |||
EXTERN char_u e_invcmd[] INIT(= N_("E476: Invalid command")); | |||
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")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably should use \"%s\"
to be consistent with the existing error messages.
} | ||
|
||
// Still alive | ||
while (remaining_tries-- && is_alive(job)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change order of operands, so that we really wait 1s. 20 consecutive jobs, that are not alive anymore at this point, decrease remaining_tries to zero without delay.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
- Add a job control module for spawning and controlling co-processes - Add three vimscript functions for interfacing with the module - Use dedicated header files for typedefs/structs in event/job modules
uv_close((uv_handle_t *)&job->proc_stdin, NULL); | ||
uv_close((uv_handle_t *)&job->proc_stderr, NULL); | ||
uv_close((uv_handle_t *)&job->proc, NULL); | ||
free(job); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it save to free job
at this point? Are all callbacks that use job
canceled (synchronously), or are they waiting for one last run of the event loop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I know it is safe. Calling uv_close
should remove any references from the event loop so no callbacks will be run after this.
kBufferLockStderr ///< Data read from stderr | ||
} BufferLock; | ||
|
||
struct _Job { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per the style-guide it should be struct job
. If job
conflicts with something then you could call it job_s
or job_struct
. Consistent rules for type names is the most useful thing that comes from a coding style guide IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed that, sorry
{ | ||
uv_disable_stdio_inheritance(); | ||
uv_prepare_init(uv_default_loop(), &job_prepare); | ||
uv_prepare_start(&job_prepare, job_prepare_cb); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tarruda Why not call uv_prepare_start
when the first job is started and call uv_prepare_stop
after the job table is empty? Otherwise the job_prepare_cb
is called every iteration of the uv loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Use debian6 package for 32bit llvm+clang, ubuntu one is actually 64bit
This is an improved version of the job control patch I sent to vim mailing list a few months ago, and it will be the base for the new plugin architecture. The job module implemented here will be reused for spawning plugins.
The basic difference between plugins and plain jobs started with
jobstart
is that instead of invoking an auto commands passing the raw data to the vimscript programmer, plugins will have access to Neovim msgpack API directlyThis is still a WIP so I'm still going to fix documentation, formatting, etc(this was basically a copy and paste from the patch)