#1171 Graceful shutdown using AbstractMain and runServices

msl Sat 7 Aug 2010

Hi,

Is there any way to perform a graceful shutdown of services launched via util::AbstractMain.runServices?

Martin

brian Sat 7 Aug 2010

The proper line of code to shutdown all services would be:

Service.list.each |service| { service.uninstall }

Maybe that belongs as a convenience somewhere, although I am not sure where it fits cleanly. As an instance method on AbstractMain doesn't seem quite right. Right now AbstractMain doesn't keep track of the services passed to runServices, and I am not sure that list would be better than all services.

jodastephen Sun 8 Aug 2010

While I don't think that the Service.list concept is that bad per se, it did feel a bit odd reading it as a static method on a trait, Fantom's equivalent of an interface. Effectively, this means that all service implementations inherit get the static method/slot to list all services. That doesn't feel quite right.

I'd note `http://fantom.org/sidewalk/topic/404` at this point. And I'm sure there was another discussion about getting the static slots as an object. Alternate solutions are a manager class - Slots are managed by a Type, Types by a Pod, but pods manage themselves like services. Is this consistent? Desirable?

msl Sun 8 Aug 2010

Thanks Brian,

I'm happy with the process for actually shutting down a service as it currently is - I don't think it needs to be any more convenient than the 50 or so characters you have there. Although I'd suggest it'd perhaps be a good move to reverse the order of startup (assuming sys::Service.list returns services in the order they were added):

Service.list.eachr |service| { service.uninstall }

My query was more based around: "how do I call service.uninstall when the user hits control-C on an AbstractMain launched app"?

I suspect control-c will have it's own set of problems, and without an equivalent of Java's Runtime.getRuntime().addShutdownHook() won't be achievable. So the alternative question becomes "how do I allow the user to do something which will then cause AbstractMain to stop the services it started?".

My gut feeling is to have another service which prompts the user to enter something to shutdown, and then stops each service, then calls Env.cur.exit - but having a separate service for that seems fairly clunky.

Martin

brian Sun 8 Aug 2010

- Slots are managed by a Type, Types by a Pod, but pods manage themselves like services. Is this consistent? Desirable?

Well the logical concept which sits above Pods is the Env. And originally back when Env was Sys, that was where find/list methods lived for pods, services, etc. But it started to become an awkward model, so I moved the list/find pattern into each class to make the API more discoverable. That pattern seems to work really well.

I suspect control-c will have it's own set of problems, and without an equivalent of Java's Runtime.getRuntime().addShutdownHook() won't be achievable.

There isn't anything today to add shutdown hooks. I personally try to design all my daemon code to never need a clean shutdown hook, but sometimes it is nice.

Should we add this feature? The API would probably look something like:

class Env
{
  Void halt(Int status := 0)   // to exit without shutdown hooks
  Void addShutdownHook(|->| f) // add func to run
}

Shutdown hooks like the JVM provide can be hard to live without in some cases. But they add a ton of rope to hang yourself too. For example I am not sure shutdown hooks should automatically stop all services - that seems too dangerous.

Login or Signup to reply.