Skip to content
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

Fix Vim crashing when querying serverlist when quitting #1427

Merged
merged 1 commit into from
Sep 9, 2023

Commits on Sep 9, 2023

  1. Fix Vim crashing when querying serverlist when quitting

    Currently, when quitting MacVim using Cmd-Q, if an autocmd queries
    serverlist() during shutdown (e.g.  VimLeavePre), there's a potential
    that Vim will crash and then stuck in a spinloop and never gets killed
    by the parent process.
    
    The reason is somehwat complicated. MMAppController tells Vim to quit
    but has a hard-coded timer before terminating the connection. If Vim
    takes too long to respond somehow, it will see a "connectionDidDie"
    message where it will be forced to quit. The serverlist() IPC API call
    isn't properly guarding against an invalid connection and if an autocmd
    triggers that call during this time, it will throw an exception and
    crash.
    
    Usually if Vim crashes, it should terminate cleanly, but couple things
    cause this to not work properly:
    - Vim's signal handler `deathtrap` tries to exit cleanly when a signal
      is detected, and it tries to call all deferred functions (added by
      :defer in Vimscript). The list of functions are allocated on the stack
      rather than the heap.
    - The ObjC exception is thrown inside a CFRunLoop (which is what called
      connectionDidDie) and CFRunLoop silently handles the exception before
      re-throwing it which triggers the actual abort signal to be caught by
      Vim's signal handler, but at this time, the deferred functions data
      structure is messed up as the stack is already gone since the first
      exception unwound it. This leads to a bogus memory state and lead to
      an infinite loop in `invoke_all_defer`.
    
    MacVim also doesn't have a solid mechanism to shut down zombie processes
    right now (it depends on Vim cleaning up after itself), so after MacVim
    quits, the now-orphaned Vim process stuck consuming 100% CPU.
    
    The fix is to simply guard against this and make sure we clean up the
    connection properly when we detected it died, and to be more defensive
    and make sure the serverlist call properly guard against invalid states
    and exceptions.
    
    Not tackling the other issues for now. There are some unfortunate
    interactions here with an unwound exception causing invoke_all_defer()
    to not work, but we just need to make sure to guard potential places
    with try/catch blocks, as invoke_all_defer() is still useful. Also,
    proper zombie process killing will be done at a later time, as we will
    soon tackle removing Distributed Objects/NSConnection and revamp the
    entire IPC stack anyway.
    
    Fix macvim-dev#1423
    ychin committed Sep 9, 2023
    Configuration menu
    Copy the full SHA
    f4e6078 View commit details
    Browse the repository at this point in the history