-
Notifications
You must be signed in to change notification settings - Fork 39
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
[ST4] Allow plugin_unloaded
to return a promise/future
#3686
Comments
I wonder if it was possible to just add a command to |
Returning a promise by This feels like massivly breaking backward compatibility. |
No this can be backwards compatible I think. The code in sublime_plugin.py can do the following checks:
|
... which could basically be done with any API function in the one way or the other which results in overcomplicating everything. Turning IMHO, without turning the whole API into asyncio There's a little bit more going on than just delaying a following |
My personal opinion would be to avoid adding async in various places in the API, mostly because I think that such APIs don't lead to better code that is easier to reason about, and implementation wise tend to be more complicated. I don't feel particularly strongly about this specific situation. If I were to approach this problem right now, I would probably something like:
Because of garbage collection, the thread will keep running doing its cleanup, but won't get in the way of modules being reloaded, or Sublime Text doing its thing. Once it is complete, the thread will end and all resources will be cleaned up/reaped. This would allow processes to be killed or shut down, it allows it to do expensive file system operations like cleaning up cache directories. It may be that a plugin needs to appropriately scope file names so they are "session"-specific and it is possible for a server to be in the process of being shut down, while another one is being started. In terms of the worker thread, items there have a few options. They could hold a reference to a variable that is poisoned during shutdown, or they could query the current generation of the plugin running in memory. |
What you describe cannot work. It may be that a TCP server has a listener socket on a specific port, let's say 8080. If you were to clean up that server in a separate thread, then the plugin_loaded call would try to start another TCP server at port 8080, which is still in use by the "poisoned" TCP server that is about to be cleaned up. The point of this issue is to reach some sort of synchronization between plugin unloads and loads. While I wrote an example of using So, the core problem is synchronization. Really, the same problem is present in |
You could write your server to not use a specific port, or you could have a way to have to stop listening during cleanup. on_exit is the same sort of thing. You just need to write your code/ infrastructure in such a way that it gets sent a signal and takes care of itself, rather than needing to block things. When it comes down to it, this is a wish for Sublime Text to change a bunch of APIs to be asynchronous because plugins want to be blocking and not asynchronous in their own responsibilities. |
Sending a signal wouldn't work because the code that would have to run to process that signal is gonna get killed on ST exit. |
Problem description
If a plugin makes heavy use of the async (worker) thread of sublime text, it can be the case that certain data structures of that plugin must be removed/cleaned up in the worker thread too, due to the design of such a plugin.
It is currently not possible to notify the plugin_host exactly when those data structures are cleaned up in the worker thread.
Consequently, when saving a python file at the root of a package directory,
plugin_unloaded
is invoked, and then immediately after that,plugin_loaded
is invoked. This forces a plugin to unload its data structures in the UI thread inplugin_unloaded
.Preferred solution
Allow a plugin to return a promise/future from
plugin_unloaded
:Note that this
sublime.Future
class doesn't actually exist. It is a hypothetical monadic future.The
sublime_plugin.py
file should then check ifplugin_unloaded
returns a future, and if so, attach a continuation to it. Only when the future resolves should the plugin be reloaded.Alternatives
N/A
Additional Information (optional)
Highly related is the thread about providing a global asyncio event loop: #3129
If SublimeHQ were to implement an event loop, it's likely a plugin would need to do asynchronous cleanup of its datastructures. In that case,
plugin_unloaded
would have tocould optimally be async:(closing a tcp server is an asynchronous operation)
The text was updated successfully, but these errors were encountered: