Skip to content

TimeoutsAndHandlers

Noah Gibbs edited this page Oct 10, 2023 · 2 revisions

Timeouts and Handlers

For Scarpe, we do everything single-threaded. Not only does Ruby have a GIL, we don't even use Ruby threads. I think that is a much, much better idea than not and I don't aim to change it. Any way of using threads, or other user-visible concurrency, is going to require app authors to think about what happens if things stop mid-handlers to start executing another handler. Not good.

But the flip side of that is: if a user puts a sleep or a long loop or something in their handler, then control will not return to the Scarpe framework. In the case of local Webview that means a crash. In the case of LibUI that means no updates to windows -- e.g. if you drag one out from under another window, the part that had been covered will remain blank instead of refreshing. Buttons will not press, selects will not happen and so on.

This is not a 100% requirement. But the ways I know to avoid it (e.g. put all app code into Fibers) are complex and don't perfectly fix the problem. At a minimum any way of fixing it that remains single-threaded in the user visible parts can't be running two user-specified handlers at once, so if one is stuck in an infinite loop, the other won't run -- so even if raw drawables remained responsive, pressing the button wouldn't run the handler in the Shoes app, for instance.

For local Webview it's worse than this, of course. A long sleep in a handler has historically resulted in a segfault, and it's pretty certainly still possible to do that, or something like it. Things like screen refresh are run via the Webview event loop, so there won't be any drawable events or redraws until we return control to Webview.

Relay-Webview (or similar possible techniques that isolate Webview into its own mostly-not-blockable process while running user-specified handlers elsewhere) can get around the crashiest parts of this, of course.

Displays, Sockets and Remote Execution

One oddity of the way we've divided our display server from our applications is that it doesn't have to be a one-to-one relationship. Shoes Classic is similar this way: it has a single display server that allows multiple Shoes apps to connect, one after another or multiple at once. You can see this in Shoes3 which just keeps running but you can open new Shoes apps into the "space" of the running Shoes server.

This architecture permits running a Shoes user app on one host and sending the display to a different host, if you want it to. And at that point we've kind of reinvented a Ruby-based version of the old X-Windows system for Unix/Linux/etc. But there's no reason you couldn't run various Shoes apps on various servers and send all the results back "home" to a display of your choice.

One reason this is interesting is that installing the display server is going to have a lot more prereqs than installing just the non-visual parts. So "display-only Scarpe" plus "remote-only Scarpe" is a potentially interesting way of packaging, especially since you can run both locally if you like.