Skip to content

Conversation

tarruda
Copy link
Member

@tarruda tarruda commented Mar 27, 2014

This removes all signal handling code from os_unix.c to os/signal.c, which
registers watchers on libuv default loop. Now signal handling will only happen
when Neovim transfers control to libuv, and SIG{HUP,TERM,QUIT} are the only
deadly signals intercepted.

I removed excessive signal handling code. For example, before it tried to handle SIGABRT which normally generates a core dump by exiting cleanly. Vim only generated core core dumps explicitly with may_core_dump function, and if the signal was received multiple times. This shouldn't happen with libuv since signals are delivered synchronously to signal_cb and only when libuv is polling for events. Signals such as SIGABRT normally mean program errors(eg: failed assertions) and should probably exit imediatelly. SIG{HUP,TERM,QUIT} are the only deadly signals we are handling because these are not related to bugs.

There may still be a resize problem with the RealWaitForChar in mch_call_shell since that still uses select/poll directly, but it should be fixed when mch_call_shell is reimplemented with libuv process facilities

@philix / @stefan991 Are the OS X redrawing problems fixed in this branch?

@tarruda tarruda changed the title Move signal handling to libuv event loop [RFC] Move signal handling to libuv event loop Mar 27, 2014
@aktau
Copy link
Contributor

aktau commented Mar 27, 2014

This is interesting. I avoid the async-signal-safe madness in my own (linux-only) apps by using signalfd. The functionality provided by libuv seems similar. Perhaps they are using the self-pipe trick as a fallback on other unices?

Admittedly I don't know enough about the original vim signal handling to say if we're not missing out on anything important by removing all the crazy core dump, reallyexit and other things...

EDIT: just confirmed they're using a variant of the self-pipe trick. The djb is strong in them...

@lslah
Copy link
Contributor

lslah commented Mar 27, 2014

@tarruda This PR is cool: It somehow fixes the failing unit test on my system I reported earlier.

@tarruda
Copy link
Member Author

tarruda commented Mar 27, 2014

One problem of this PR is that vim has got_int tests all over the place and probably some of those assume asynchronous delivery of signals.

Most of the times that cannot be the case, since when the terminal is in raw mode(most of the times it should be) ctrl+c doesn't generate a SIGINT and vim has to read the key sequence explicitly, but I still need to make sure libuv is polled every time the terminal is set to cooked(that should probably be fixed by adding a calls to event_poll in those places)

@tarruda
Copy link
Member Author

tarruda commented Mar 27, 2014

I used the following test:

while 1
  let c = 123
endwhile

That inifinite loop is always interrupted by sending an INT signal from another terminal, no matter if its passed as a -c argument or if vim is in ex mode so my guess is that vim always polls for characters(and consequently for signals) which should make this PR ok

@justinmk
Copy link
Member

Awesome!

@oni-link
Copy link
Contributor

CTRL-C in insert-mode changes at once into normal mode, but
if I send SIG_INT to nvim the mode change only takes place after an additional key is pressed.
Should the event loop be exited on an got_int?

@tarruda
Copy link
Member Author

tarruda commented Mar 27, 2014

@oni-link Yes that would be a good way to handle with the situation

@jamessan
Copy link
Member

Doesn't this cause a change in behavior where neovim will now not try to flush swapfiles, etc. (i.e., everything done in preserve_exit) except when SIGTERM/SIGQUIT/SIGHUP are received?

Previously Vim would call preserve_exit for any deadly signal.

@tarruda
Copy link
Member Author

tarruda commented Mar 27, 2014

@jamessan The question is: Should vim continue running on a fatal error such as a SIGSEGV/SIGABRT? It's very likely those are caused by bugs so perhaps the safest action is the default one: exit as soon as possible and generate a core dump.

Considering that vim already flushes swapfiles every 4 seconds, the loss of work, if any, wouldn't be significant. On the other hand, by assuming that we only handle normal signals such as INT/HUP/TERM, we can execute unsafe actions in the deadly handler. The VimLeave autocommand will be much more useful like this.

@tarruda
Copy link
Member Author

tarruda commented Mar 27, 2014

If no one objects these changes, I will merge them tomorrow

@felipecrv
Copy link
Contributor

@tarruda I did some resizings, :vs... While normally using nvim it freezes.

I attached gdb to it. See http://pastie.org/8975268

@felipecrv
Copy link
Contributor

@tarruda previous nvim revision doesn't freeze after rapidly and repeatedly resizing the console.

@tarruda
Copy link
Member Author

tarruda commented Mar 28, 2014

@philix how to reproduce this freeze? Does the freeze happens in the kevent call?

@tarruda
Copy link
Member Author

tarruda commented Mar 28, 2014

I'm resizing very fast with the keyboard but still couldn't reproduce, I wonder if this is OSX-specific. @stefan991 can you reproduce this?

@philix when you said the previous revision didn't freeze, you meant the revision on master without this new signal handling code right?

@stefan991
Copy link
Contributor

@tarruda Got this while compiling the last commit:

[ 97%] Building C object src/CMakeFiles/nvim.dir/os/signal.c.o
/Users/stefan/Dev/neovim/src/os/signal.c:62:10: error: use of undeclared
      identifier 'SIGPWR'
    case SIGPWR:
         ^
/Users/stefan/Dev/neovim/src/os/signal.c:103:10: error: use of undeclared
      identifier 'SIGPWR'
    case SIGPWR:
         ^
2 errors generated.
make[3]: *** [src/CMakeFiles/nvim.dir/os/signal.c.o] Error 1
make[2]: *** [src/CMakeFiles/nvim.dir/all] Error 2
make[1]: *** [all] Error 2
make: *** [nvim] Error 2

using commit 1567cc5 i could reproduce the resizing bug. Neovim dosn't handle input any more, but resiszing does continue to work. It takes some tries, but I could reproduce it more than 5 times. One time I had the case that the input took some seconds to show up. But I could only reproduce it with my .nvimrc, using nvim -u NONE this didn't happen. My guess would be that this has something to do with redrawing the status line.

stefan at air in ~/Dev/neovim on git:(unknown)
% lldb 
(lldb) process attach -n nvim
Process 16559 stopped
Executable module set to "/Users/stefan/Dev/neovim/build/bin/nvim".
Architecture set to: x86_64-apple-macosx.
(lldb) thread backtrace
* thread #1: tid = 0x5da076, 0x00007fff8cf6a64a libsystem_kernel.dylib`kevent + 10, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  * frame #0: 0x00007fff8cf6a64a libsystem_kernel.dylib`kevent + 10
    frame #1: 0x000000010d23e54d nvim`uv__io_poll(loop=0x000000010d280a88, timeout=<unavailable>) + 669 at kqueue.c:130
    frame #2: 0x000000010d22fad8 nvim`uv_run(loop=0x000000010d280a88, mode=UV_RUN_ONCE) + 328 at core.c:294
    frame #3: 0x000000010d22b9a2 nvim`event_poll(ms=-1) + 162 at event.c:59
    frame #4: 0x000000010d22cadf nvim`inbuf_poll(ms=-1) + 47 at input.c:179
    frame #5: 0x000000010d22ca4c nvim`os_inchar(buf=0x000000010d27a34c, maxlen=52, ms=-1, tb_change_cnt=149) + 204 at input.c:143
    frame #6: 0x000000010d213ed6 nvim`ui_inchar(buf=0x000000010d27a34c, maxlen=52, wtime=-1, tb_change_cnt=149) + 166 at ui.c:159
    frame #7: 0x000000010d0c1355 nvim`inchar(buf=0x000000010d27a34c, maxlen=156, wait_time=-1, tb_change_cnt=149) + 581 at getchar.c:2485
    frame #8: 0x000000010d0c5d93 nvim`vgetorpeek(advance=1) + 7203 at getchar.c:2300
    frame #9: 0x000000010d0c38e2 nvim`vgetc + 242 at getchar.c:1391
    frame #10: 0x000000010d0c608d nvim`safe_vgetc + 13 at getchar.c:1511
    frame #11: 0x000000010d12507a nvim`normal_cmd(oap=0x00007fff52c08748, toplevel=1) + 394 at normal.c:580
    frame #12: 0x000000010d0e6641 nvim`main_loop(cmdwin=0, noexmode=0) + 1889 at main.c:776
    frame #13: 0x000000010d0e3408 nvim`main(argc=1, argv=0x00007fff52c08970) + 1848 at main.c:560
(lldb) 

@stefan991
Copy link
Contributor

@tarruda: I think I found the stack trace that causes Neovim to ignore input after resizing: (using commit 1567cc5)

(lldb) thread backtrace
* thread #1: tid = 0x5e7447, 0x0000000103794824 nvim`input_stop + 4 at input.c:87, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
  * frame #0: 0x0000000103794824 nvim`input_stop + 4 at input.c:87
    frame #1: 0x00000001037939fb nvim`event_poll(ms=0) + 251 at event.c:68
    frame #2: 0x0000000103794b81 nvim`os_breakcheck + 33 at input.c:169
    frame #3: 0x000000010377c059 nvim`ui_breakcheck + 9 at ui.c:276
    frame #4: 0x000000010367ff5f nvim`line_breakcheck + 47 at misc1.c:3860
    frame #5: 0x00000001035a83ed nvim`call_user_func(fp=0x00007feca3625ff0, argcount=0, argvars=0x00007fff5c6958c0, rettv=0x00007fff5c6960d0, firstline=1, lastline=1, selfdict=0x0000000000000000) + 157 at eval.c:18426
    frame #6: 0x0000000103597e6e nvim`call_func(funcname=0x00007fff5c697785, len=25, rettv=0x00007fff5c6960d0, argcount=0, argvars=0x00007fff5c6958c0, firstline=1, lastline=1, doesrange=0x00007fff5c695b3c, evaluate=1, selfdict=0x0000000000000000) + 1374 at eval.c:7378
    frame #7: 0x000000010359ac9f nvim`get_func_tv(name=0x00007fff5c697785, len=25, rettv=0x00007fff5c6960d0, arg=0x00007fff5c696048, firstline=1, lastline=1, doesrange=0x00007fff5c695b3c, evaluate=1, selfdict=0x0000000000000000) + 431 at eval.c:7237
    frame #8: 0x00000001035c0cf1 nvim`eval7(arg=0x00007fff5c696048, rettv=0x00007fff5c6960d0, evaluate=1, want_string=0) + 1585 at eval.c:4519
    frame #9: 0x00000001035c0282 nvim`eval6(arg=0x00007fff5c696048, rettv=0x00007fff5c6960d0, evaluate=1, want_string=0) + 66 at eval.c:4229
    frame #10: 0x00000001035bfdb6 nvim`eval5(arg=0x00007fff5c696048, rettv=0x00007fff5c6960d0, evaluate=1) + 70 at eval.c:4081
    frame #11: 0x00000001035bef39 nvim`eval4(arg=0x00007fff5c696048, rettv=0x00007fff5c6960d0, evaluate=1) + 73 at eval.c:3826
    frame #12: 0x00000001035bed1a nvim`eval3(arg=0x00007fff5c696048, rettv=0x00007fff5c6960d0, evaluate=1) + 42 at eval.c:3746
    frame #13: 0x00000001035beb0a nvim`eval2(arg=0x00007fff5c696048, rettv=0x00007fff5c6960d0, evaluate=1) + 42 at eval.c:3683
    frame #14: 0x0000000103596bf3 nvim`eval1(arg=0x00007fff5c696048, rettv=0x00007fff5c6960d0, evaluate=1) + 35 at eval.c:3616
    frame #15: 0x0000000103596754 nvim`eval0(arg=0x00007fff5c697785, rettv=0x00007fff5c6960d0, nextcmd=0x00007fff5c696c88, evaluate=1) + 52 at eval.c:3578
    frame #16: 0x0000000103596e6d nvim`eval_to_string(arg=0x00007fff5c697785, nextcmd=0x00007fff5c696c88, convert=0) + 61 at eval.c:1299
    frame #17: 0x00000001035970ed nvim`eval_to_string_safe(arg=0x00007fff5c697785, nextcmd=0x00007fff5c696c88, use_sandbox=0) + 93 at eval.c:1335
    frame #18: 0x000000010356cf54 nvim`build_stl_str_hl(wp=0x00007feca381ea00, out=0x00007fff5c697770, outlen=1024, fmt=0x00007feca358a430, use_sandbox=0, fillchar=32, maxwidth=88, hltab=0x00007fff5c697260, tabtab=0x00007fff5c696d60) + 5044 at buffer.c:3165
    frame #19: 0x00000001037186f0 nvim`win_redr_custom(wp=0x00007feca381ea00, draw_ruler=0) + 1168 at screen.c:5013
    frame #20: 0x00000001037133e2 nvim`redraw_custom_statusline(wp=0x00007feca381ea00) + 82 at screen.c:4835
    frame #21: 0x000000010370a121 nvim`win_redr_status(wp=0x00007feca381ea00) + 209 at screen.c:4732
    frame #22: 0x0000000103705446 nvim`update_screen(type=40) + 1782 at screen.c:592
    frame #23: 0x0000000103776277 nvim`set_shellsize(width=0, height=0, mustset=0) + 599 at term.c:2599
    frame #24: 0x00000001037775a4 nvim`shell_resized + 20 at term.c:2493
    frame #25: 0x0000000103794e6d nvim`signal_cb + 205
    frame #26: 0x000000010379e415 nvim`uv__signal_event(loop=0x00000001037e8a88, w=<unavailable>, events=<unavailable>) + 213 at signal.c:386
    frame #27: 0x00000001037a688c nvim`uv__io_poll(loop=0x00000001037e8a88, timeout=<unavailable>) + 1500 at kqueue.c:232
    frame #28: 0x0000000103797ad8 nvim`uv_run(loop=0x00000001037e8a88, mode=UV_RUN_ONCE) + 328 at core.c:294
    frame #29: 0x00000001037939a2 nvim`event_poll(ms=-1) + 162 at event.c:59
    frame #30: 0x0000000103794adf nvim`inbuf_poll(ms=-1) + 47 at input.c:179
    frame #31: 0x0000000103794a4c nvim`os_inchar(buf=0x00000001037e22ed, maxlen=83, ms=-1, tb_change_cnt=3) + 204 at input.c:143
    frame #32: 0x000000010377bed6 nvim`ui_inchar(buf=0x00000001037e22ed, maxlen=83, wtime=-1, tb_change_cnt=3) + 166 at ui.c:159
    frame #33: 0x0000000103629355 nvim`inchar(buf=0x00000001037e22ed, maxlen=251, wait_time=-1, tb_change_cnt=3) + 581 at getchar.c:2485
    frame #34: 0x000000010362dd93 nvim`vgetorpeek(advance=1) + 7203 at getchar.c:2300
    frame #35: 0x000000010362b8e2 nvim`vgetc + 242 at getchar.c:1391
    frame #36: 0x000000010362e08d nvim`safe_vgetc + 13 at getchar.c:1511
    frame #37: 0x000000010368d07a nvim`normal_cmd(oap=0x00007fff5c6a0748, toplevel=1) + 394 at normal.c:580
    frame #38: 0x000000010364e641 nvim`main_loop(cmdwin=0, noexmode=0) + 1889 at main.c:776
    frame #39: 0x000000010364b408 nvim`main(argc=1, argv=0x00007fff5c6a0970) + 1848 at main.c:560
(lldb) 

input_stop() gets called, but input_start() isn't called while handling SIGWINCH.

@aktau
Copy link
Contributor

aktau commented Mar 28, 2014

Just out of curiosity, how did you get that stacktrace? Checking out the input_stop function doesn't show me anything that could block so I assume you put a breakpoint there (inspecting the libuv source tells me that neither uv_idle_stop nor uv_read_stop block).

Actually, I just noticed that your stacktrace calls event_poll recursively (of course). I wonder if this usage was taken into account while coding input.c and event.c. It must be, otherwise very little would work, but perhaps there's a bit of reentrancy issues here.

(notes for me personally)
call graphs:

  • input_start: by event_poll at os/event.c:36
  • input_stop: by event_poll at os/event.c:62
  • event_poll:
    • by os_breakcheck at os/input.c:169
    • by inbuf_poll at os/input.c:179

@stefan991
Copy link
Contributor

@aktau yes, I did add symbolic breakpoints for input_start, input_stop and shell_resized. First I used the Xcode feature to add a debug log message and continue automatically after hitting the breakpoint on the 3 functions to see the order they were called. As input_stop was called after resizing the window I disabled the automatic continue on that breakpoint and ran thread backtrace to get the stacktrace.

@tarruda
Copy link
Member Author

tarruda commented Mar 29, 2014

@stefan991 Thanks for debugging this for me. At first I didn't consider the possibility of event_loop being called recursively now after seeing your stacktrace its obvious this will happen, especially when co-processes or the msgpack APIs are implemented.

@tarruda
Copy link
Member Author

tarruda commented Mar 29, 2014

@stefan991 / @philix does that last commit fixes the freeze bug?

Also if anyone has a better way of working around this issue I'm all ears. Personally I hate how vim uses global variables to make functions behave differently on recursion, but I couldn't find a better solution here.

The problem is that vim event loop isn't sane in the sense that it needs to call itself

@stefan991
Copy link
Contributor

@tarruda: I'm getting Vim: Error reading input, exiting... while resizing. Using a breakpoint on read_error_exit I'm getting this stacktrace:

(lldb) thread backtrace
* thread #1: tid = 0x61593f, 0x000000010047666f nvim`read_error_exit + 15 at ui.c:572, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x000000010047666f nvim`read_error_exit + 15 at ui.c:572
    frame #1: 0x00000001004764ea nvim`fill_input_buf(exit_on_error=1) + 506 at ui.c:529
    frame #2: 0x000000010047623a nvim`read_from_input_buf(buf=0x00007fbd09407350, maxlen=67) + 42 at ui.c:465
    frame #3: 0x000000010048ea9e nvim`os_inchar(buf=0x00007fbd09407350, maxlen=67, ms=-1, tb_change_cnt=181) + 286 at input.c:156
    frame #4: 0x0000000100475e96 nvim`ui_inchar(buf=0x00007fbd09407350, maxlen=67, wtime=-1, tb_change_cnt=181) + 166 at ui.c:159
    frame #5: 0x0000000100323315 nvim`inchar(buf=0x00007fbd09407350, maxlen=202, wait_time=-1, tb_change_cnt=181) + 581 at getchar.c:2485
    frame #6: 0x0000000100327d53 nvim`vgetorpeek(advance=1) + 7203 at getchar.c:2300
    frame #7: 0x00000001003258a2 nvim`vgetc + 242 at getchar.c:1391
    frame #8: 0x000000010032804d nvim`safe_vgetc + 13 at getchar.c:1511
    frame #9: 0x000000010038703a nvim`normal_cmd(oap=0x00007fff5f9a6748, toplevel=1) + 394 at normal.c:580
    frame #10: 0x0000000100348601 nvim`main_loop(cmdwin=0, noexmode=0) + 1889 at main.c:776
    frame #11: 0x00000001003453c8 nvim`main(argc=1, argv=0x00007fff5f9a6970) + 1848 at main.c:560
(lldb) 

@tarruda
Copy link
Member Author

tarruda commented Mar 29, 2014

@stefan991 what steps did you take to reproduce this? Only a simple resize?

@tarruda
Copy link
Member Author

tarruda commented Mar 29, 2014

@stefan991 are you running this with -u NONE ? I wonder if you have a plugin that listens for VimResized

if (entered++) {
// We don't want recursion because the loop should only start once, for
// now use this hack to prevent it.
return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible that recursively two calls to poll functions, both with ms < 0, are made? Would the caller not expect a result for the second call?

A call graph for this scenario (no input made):

os_inchar(...,ms=-1,...) -> 
inbuf_poll(-1) -> 
resize (results in a second blocking *_poll call) -> 
os_inchar(...,ms=-1,...) -> 
inbuf_poll(-1) -> 
read_from_input_buf() -> 
fill_input_buf(exit_on_error) -> 
read_error_exit()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, I guess this problem needs to be handled differently

@stefan991
Copy link
Contributor

@tarruda: I resized the terminal window several seconds with the mouse. Couldn't reproduce this with nvim -u NONE. Here is my .nvimrc and a list of installed plugins: https://gist.github.com/stefan991/9855755 (I should probably update my dotfiles reopo later)

@stefan991
Copy link
Contributor

@tarruda: Ack didn't find an occurrence of VimResized in my .nvim folder.

@stefan991
Copy link
Contributor

@tarruda: looks good on OSX.

@felipecrv
Copy link
Contributor

@tarruda looks good on OSX. No resize/redraw issues.

@tarruda
Copy link
Member Author

tarruda commented Mar 31, 2014

I've opened #434 to deal with the data structure boilerplate, lets leave it like this for now and use a separate PR after the library is decided.

I've also removed the K_EVENT special key and left all the event handling code into event.c. The main goal of K_EVENT was to avoid recursion of libuv ev_run but it should be covered by the new event_poll implementation. The advantage of the new approach is that we avoid repeating calls to process_all_events(old event_handle)

The last update is working well on linux, if it doesn't break anything for OS X users then I will squash/merge.

@oni-link
Copy link
Contributor

  • Don't we still have the recursion problem if resize calls somehow event_poll?
  • In case of signals the timeout duration can exceed ms, because the event_poll loop
    iterates until no signal occured.
  • Signal SIGINT cancels the loop only after additional keys are pressed.

@oni-link
Copy link
Contributor

With the following nvimrc nvim -u nvimrc aborts when resizing:

set nocompatible
filetype off
set rtp+=~/.vim/bundle/vundle/
call vundle#rc()

Bundle 'gmarik/vundle'
Bundle 'itchyny/lightline.vim'

syntax on
filetype plugin indent on

set laststatus=2

@tarruda
Copy link
Member Author

tarruda commented Mar 31, 2014

@oni-link

Don't we still have the recursion problem if resize calls somehow event_poll?

The problem was recursion into uv_run, that should be avoided by moving most of the code from event_poll to poll_uv_loop and calling process_all_events outside poll_uv_loop

In case of signals the timeout duration can exceed ms, because the event_poll loop
iterates until no signal occured.

Yes need to take that into account

Signal SIGINT cancels the loop only after additional keys are pressed.

I think the last commit should have fixed it(Can you confirm?)

As for the abort, it was caused by process_all_events(the default switch branch). I'm inspecting the core dump

@oni-link
Copy link
Contributor

@tarruda

I think the last commit should have fixed it(Can you confirm?)

After the first SIGINT you still need another signal or input if event_poll was called
with ms < 0, because the event is handled in the next loop iteration.

@tarruda
Copy link
Member Author

tarruda commented Mar 31, 2014

@oni-link What do you think about this latest version? Did it address every item in your list correctly?

@oni-link
Copy link
Contributor

@tarruda The exit condition in the event_poll loop (while part) is not right.
You would exit the loop for ms<0 and signals(resize) but no input.

Is it okay to leave the event queue unprocessed if exiting the loop?

The stacking timeout problem would be solved with this solution. You can always exit the loop for ms>=0 (if you are okay with unprocessed events).

@tarruda
Copy link
Member Author

tarruda commented Mar 31, 2014

@oni-link I understand the ms<0 condition but why exit on resize? Invoking shell_resized directly from process_all_events should not be a problem

I dont see a problem with leaving the queue unprocessed, but I cant see the stacking timeout problem you mention, can you give an example?

@oni-link
Copy link
Contributor

@tarruda I try to construct a case where you would exit.
If you block for input (ms<0), you expect to get something back, at least a byte or got_int.
While waiting for input, you resize the window and because of that you exit both loops. The resize event is not processed (rv == false, has_pending_events() == true). You return through the call stack and end up in fill_input_buf(exit_on_error=1). Here you try to read at least one byte, but that fails, so you exit.

'Stacking timeout problem': That was a problem before 8a2bdec.
You call event_poll with ms>0 and while you wait for the timeout in poll_uv_loop you resize and return to event_poll. Before 8a2bdec you could not leave the loop, because has_pending_events()==true. So you have to loop again and call poll_uv_loop with the same
timeout as the first time. Repeat this a few times and you can spent more than ms ms in event_poll.
With the additional conditon (rv) this can not happen anymore.

@tarruda
Copy link
Member Author

tarruda commented Apr 1, 2014

@oni-link I missed that case, thanks for showing me. I have refactored the event_poll loop, it should be simpler to understand and it also subtracts the ellapsed time in case of ms > 0

@tarruda
Copy link
Member Author

tarruda commented Apr 1, 2014

Squash/rebase

{
Event *event = (Event *)malloc(sizeof(Event));
event->type = kEventSignal;
event->data = malloc(sizeof(int));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xmalloc instead of malloc

@tarruda
Copy link
Member Author

tarruda commented Apr 1, 2014

It seem pretty stable, and now we can use VimLeave/VimLeavePre to perform custom cleanup :)

I will do some more tests and will squash/merge it the next half-hour or so

This removes all signal handling code from os_unix.c to os/signal.c. Now signal
handling is done like this:

- Watchers for signals are registered with libuv default event loop
- `event_poll` continuously calls `poll_uv_loop` to produce events until it
  receives user input, SIGINT or a timeout
- Any signals received in `poll_uv_loop` will push events to a queue that is
  drained and processed by `event_poll`

Signals aren't handled directly in the libuv callback to avoid recursion in the
event loop(which isn't supported by libuv).

The same principle will apply to other events in the future: Push to a queue
from a libuv callback and drain it from `event_poll`
@tarruda tarruda merged commit 774f668 into neovim:master Apr 1, 2014
@tarruda
Copy link
Member Author

tarruda commented Apr 1, 2014

done, now move on to the shell/co-process infrastructure

@felipecrv
Copy link
Contributor

done, now move on to the shell/co-process infrastructure

\o/

tarruda referenced this pull request in tarruda/neovim Apr 22, 2014
- Add channel module that exposes the API over arbitrary streams
- Add `xmemdup` for duplicating memory chunks
- Make job exit callback optional
justinmk pushed a commit that referenced this pull request Feb 17, 2016
Problem:    Vim doesn't recognize all htmldjango files.
Solution:   Recognize a comment. (Daniel Hahler, PR #410)

vim/vim@d8986fd
mgraczyk pushed a commit to mgraczyk/neovim that referenced this pull request Feb 29, 2016
Problem:    Vim doesn't recognize all htmldjango files.
Solution:   Recognize a comment. (Daniel Hahler, PR neovim#410)

vim/vim@d8986fd
dwb pushed a commit to dwb/neovim that referenced this pull request Feb 21, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants