sublime_lib icon indicating copy to clipboard operation
sublime_lib copied to clipboard

Spawn a separate process using the system's Python to track when ST is closed and allow cleanups

Open FichteFoll opened this issue 4 years ago • 9 comments

This is something that ST just cannot do at the moment and thus leaves plugins mostly struggling to clean up their resources or whatever. Because it's something that can be reused easily and only needs a single guardian process, there should be a centralized solution and sublime_lib provides a good opportunity to do so.

In essence:

  1. Provide an interface that users can call with the path to an executable (script) that will be run once it is detected that ST has been shut down. Also pass provided arguments to the subprocess call.
  2. On the first of such call, spawn a subprocess using the system python that will monitor its parent existence and has a communication channel with the plugin so that more on_exit executables can be added.
  3. Once ST has been closed, run the specified scripts with the respective arguments in parallel.

Optional: Log errors or failed calls in some log file, probably in the cache.

I suppose using standard pipes for communication and declaring ST as having closed when the pipe is broken works, too.

Related: https://github.com/SublimeTextIssues/Core/issues/2950

FichteFoll avatar Aug 23 '19 11:08 FichteFoll

Since Windows doesn't ship Python by default, we may be able to get the same result with a PowerShell script. I can't really help with that, however.

FichteFoll avatar Sep 19 '19 20:09 FichteFoll

If it is not found installed, we could ship some Python :stuck_out_tongue: Python is good for your health :innocent:

evandrocoan avatar Sep 20 '19 01:09 evandrocoan

The good news is that Sublime already comes with a perfectly serviceable Python interpreter: plugin_host. The bad news is that a) this is the thing that we want to wait on, and it can't wait on itself, and b) it doesn't end via sys.exit() so we can't use atexit to register exit handlers.

What we can do, though, is:

1. Fork plugin_host.
2a. In the parent, os.wait() for the child. 2b. In the child:     1. Do normal daemonization stuff (close fds, chdir, whatever).     2. Fork.     3a. In the parent, os._exit(0).     3b. In the child:         1. Set an atexit handler to:             1. Sleep in a loop until the original plugin_host PID is gone.             2. Run cleanup code.         2. sys.exit(0).

Thom1729 avatar Sep 20 '19 02:09 Thom1729

Reusing plugin_host is a neat idea because it means packages don't need to provide executables (and a .no-sublime-package), since we can run the cleanup code from within ST's environment. Unfortunately, again, this won't work on Windows.

Why do we need to os.wait() though? couldn't we just use the first child already?

FichteFoll avatar Sep 20 '19 12:09 FichteFoll

Unfortunately, again, this won't work on Windows.

Ugh. I forgot that Windows doesn't have fork. Is there a similar strategy that might work for Windows? The important thing about fork is that it allows you to continue execution in a Python interpreter that's already set up and ready to go, without worrying about how to initialize plugin_host or about multiple hosts interfering with each other. (It occurs to me that a hypothetical version of Sublime supporting a new Python runtime might be better behaved in this regard.)

Why do we need to os.wait() though? couldn't we just use the first child already?

I'm cribbing from the standard double-fork daemonization strategy. The purpose of the double-fork has to do with setsid(); I forget the details. Our implementation might vary.

Thom1729 avatar Sep 20 '19 13:09 Thom1729

Apparently this issue is also related: https://github.com/SublimeTextIssues/Core/issues/10 (duplicate to the above mentioned).

And though it is an old issue, it was added to their "next dev cycle" milestone recently!

neuged avatar Oct 02 '19 09:10 neuged

Oh, sneaky. I didn't notice that. Thanks for the heads-up.

FichteFoll avatar Oct 02 '19 13:10 FichteFoll

Since this has been added for the new environment in 4050+, I believe we don't need this anymore, though I haven't tested it yet.

FichteFoll avatar Jan 21 '20 03:01 FichteFoll

Agree, I think the ability to do cleanups by on_exit event handlers is enough. The idea of starting arbitrary scripts upon or after application exit feels like a hack. The dependency of external script interpreters even makes it awkward and error prone.

Plugins should be able to do cleanups upon application startup etc. in case ST crashed and therefore didn't call on_exit.

deathaxe avatar Feb 29 '20 12:02 deathaxe