-
-
Notifications
You must be signed in to change notification settings - Fork 683
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
After quitting MacVim a vim process consuming 99.8% CPU is left #1423
Comments
Huh that's not great. So basically Vim crashed and yet is using max CPU? One thing that's been on my TODO list is to expose crash logs better so it's easier for users to find them. I posted some instructions at this comment before (#1407 (comment)). Basically you can directly find them in Console.app, or |
@ychin Here is the I also had the following in the terminal:
|
Oh interesting. That helps a lot! I just happen to be looking at that part of the code for unrelated reasons. Thanks for the logs. |
After some initial investigation, this is a weird confluence of factors due to how the IPC mechanism works (which is quite outdated and needs to be replaced in #1157). In particular, during shutdown, an autocmd triggers a I will submit a fix, but for now, if this bugs you, you could identify which plugin/config is calling |
Actually are you sure you were doing Cmd-W when that happened? Or do you think you could be hitting Cmd-Q instead? It's fine if you don't remember, but it's just that the callstack makes me believe that was a Cmd-Q instead, although I'm still not sure. |
Thanks. I think in this case I did cmd + Q. |
Actually when I observed more carefully most of the time the issue happens is when Cmd + Q is clicked. 🙄 What usually happens is I Cmd + Q and then work on something else. There I do Cmd + W and then notice the error and Activity Log, I wrongly associated this with Cmd + W. Sorry for misleading |
Cool, thanks. There are actually a fair bit of issues with the current way that MacVim is structured as it's vulnerable to zombie orphaned Vim processes if something went wrong, so I'm trying to prioritize fixing the immediate issue first. I think the Cmd + Q one is easy to identify and fix so that's good to hear. |
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, and invoke all deferred functions. These are added to the stack when we enter a new autocmd. - 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
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
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
Steps to reproduce
Cmd + WCmd + QWhat happens
This happens some times.
Can't really catch when.
Usually I catch it by seeing the following in the terminal
Then I open Activity Monitor and check for VIM
I noticed this happening about ~3 weeks ago. Might have happen before that.
One week ago I added github-copilot to my vimrc, but this issue was happening before that
Expected behaviour
Close MacVim and all related issues.
Version of Vim and architecture
MacVim r177 (Vim 9.0.1677)
Environment
OS: 13.4.1 (c) (22F770820d)
Model: Mac Book Pro
Processor: Apple M1 Max
How MacVim was installed
Downloaded
Logs and stack traces
No response
Vim configuration where issue is reproducable
https://github.com/RStankov/config_files/blob/master/dot/vimrc
Issue has been tested with given configuration
Issue has been tested with no configuration
mvim --clean
(orgvim
, supplied by MacVim distribution)vim --clean
(in terminal, supplied by MacVim distribution)vim --clean
(in terminal, other suppliers, e.g. /usr/bin/vim)The text was updated successfully, but these errors were encountered: