+1 for graceful shutdown. It could also be useful for coarse, multi-protocol use cases such as using BLE for commissioning, shutting down that stack, and then starting a 15.4 stack such as Thread.
In general, it would be great if nimble could support high level stack start / stop commands such as the following shell API imply: ble start # start nimble stack ble scan start # start BLE scan ... ble scan stop # stop BLE scan *ble stop *# NEW: gracefully shutdown nimble All of the above can be supported right now, except "ble stop", so your proposal is welcome. I would also suggest keeping the concepts of graceful shutdown and reset separable. Martin _____________________________ Martin Turon | Google On Fri, Sep 28, 2018 at 4:18 PM, will sanfilippo <wi...@runtime.io> wrote: > Some comments: > > 1) Are there are any other cases you can see for a controlled shutdown? I > get the reset command. I am trying to think of others. > 2) I am curious: how do you know how many of these functions, or which > ones, return in progress? Curious to know how you were going to implement > that specifically. > > Otherwise, sounds good and seems like a good addition to mynewt! > > > > On Sep 28, 2018, at 1:08 PM, Christopher Collins <ch...@runtime.io> > wrote: > > > > Hello all, > > > > I have been looking into implementing a graceful shutdown for Mynewt. > > The system may want to perform a cleanup procedure immediately before it > > resets, and I wanted to allow this procedure to be configured. I am > > calling this shutdown facility "sysdown", as a counterpart to "sysinit". > > > > ### BASIC IDEA: > > > > My idea is to allow each Mynewt package to specify a sequence of > > shutdown function calls, similar to a package's `pkg.init` function call > > list. The newt tool would generate a C shutdown function called > > `sysdown()`. This function would consist of calls to each package's > > shutdown functions. When a controlled shutdown is initiated, > > `sysdown()` would be called prior to the final call to > > `hal_system_reset()`. > > > > To clarify, this procedure would only be performed for a controlled > > shutdown. It would be executed when the system processes a newtmgr > > "reset" command, for example. It would not be executed when the system > > crashes, browns out, or restarts due to the hardware watchdog. > > > > I think this scheme is pretty straightforward and I see no issues so far > > (but please pipe up if this doesn't seem right!). > > > > ### PROBLEM: > > > > Then I tried applying this to an actual use case, and of course I > > immediately encountered some problems :). > > > > My actual use case is this: when I reset the Mynewt device, I would like > > the nimble stack to gracefully terminate all open Bluetooth connections. > > This isn't strictly necessary; the connected peer will eventually > > realize that the connection has dropped some time after the reset. The > > problem is that Android centrals take a really long time to realize that > > the connection has dropped, as described here: > > https://blog.classycode.com/a-short-story-about-android-ble- > connection-timeouts-and-gatt-internal-errors-fa89e3f6a456. > > So, I wanted to explicitly terminate the connections to speed up the > > process. > > > > Ideally, I could configure the nimble host package with a shutdown > > callback that just performs a blocking terminate of each open > > connection in sequence. Unfortunately, the nimble host is likely > > running in the same task as the one that initiated the shutdown, so it > > is not possible to perform a blocking operation. Instead, the running > > task needs to terminate each connection asynchronously: enqueue a GAP > > terminate procedure, then return so that the task can process its event > > queue. Eventually, the BLE terminate procedure will complete, and the > > result of the procedure will be indicated via an event on this event > > queue. The sysdown mechanism I described earlier in this email doesn't > > allow for asynchronous procedures. It reboots the system immediately > > after executing all the shutdown callbacks. > > > > I think this will be a common issue for other packages, so I am > > trying to come up with a general solution. > > > > ### SOLUTION: > > > > Each shutdown callback returns one of the following codes: > > * SYSDOWN_COMPLETE > > * SYSDOWN_IN_PROGRESS > > > > When a controlled reset is initiated, the shutdown facility executes > > every confgured callback. If all callbacks return `SYSDOWN_COMPLETE`, > > then the procedure is done; the system completes the reset with a call > > to `hal_system_reset()`. > > > > If one or more callbacks returns `SYSDOWN_IN_PROGRESS`, then the > > shutdown facility needs to wait for those subprocedures to complete. > > Each in-progress shutdown subprocedure indicates completion > > asynchronously via a call to `sysdown_complete()`. When the last > > remaining entry signifies completion, the shutdown facility finishes the > > shutdown procedure with a call to `hal_system_reset()`. To defend > > against hanging subprocedures, the system can be configured to crash if > > the shutdown procedure takes too long. > > > > Does that sound reasonable? All comments welcome. > > > > Thanks, > > Chris > >