Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Register
  • Sign in
  • Briar Mailbox Briar Mailbox
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
  • Issues 21
    • Issues 21
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 1
    • Merge requests 1
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • briarbriar
  • Briar MailboxBriar Mailbox
  • Issues
  • #158
Closed
Open
Issue created Aug 11, 2022 by Sebastian@sebkurDeveloper

CLI does not respond to Ctrl+C any longer

Ctrl+C is supposed to shutdown the CLI app and we also want to shutdown the lifecycle cleanly before exiting. To achieve this, we register a shutdown hook before starting the lifecycle which gets called in response to the signal.

Note: it looks like the shutdown hooks do not (and did never) run when the mailbox cli is run using gradle, i.e. ./gradlew run --args=-v won't trigger the shutdown hooks when a shutdown signal is received. So we need to build the jar using ./gradlew x86LinuxJar and run it using java -jar mailbox-cli/build/libs/mailbox-cli-linux-x86_64.jar to observe if things are working or not.

Currently, pressing Ctrl+C leads to a deadlock. This is what is happening:

  • Ctrl+C initiates a shutdown of the VM
  • The shutdown hooks get started, including the one we registered before starting the lifecycle
  • our shutdown hook calls LifecycleManager#stopServices()
  • stopServices() calls exitProcess(0) in its finally block
  • This leads to deadlock.

The cause for the deadlock is described in the documentation of Runtime#exit:

Terminates the currently running Java virtual machine by initiating its shutdown sequence. [...]

The virtual machine's shutdown sequence consists of two phases. In the first phase all registered shutdown hooks, if any, are started in some unspecified order and allowed to run concurrently until they finish. In the second phase all uninvoked finalizers are run if finalization-on-exit has been enabled. Once this is done the virtual machine halts.

If this method is invoked after the virtual machine has begun its shutdown sequence then if shutdown hooks are being run this method will block indefinitely. If shutdown hooks have already been run and on-exit finalization has been enabled then this method halts the virtual machine with the given status code if the status is nonzero; otherwise, it blocks indefinitely.

The important part being:

If this method is invoked after the virtual machine has begun its shutdown sequence then if shutdown hooks are being run this method will block indefinitely

And that is precisely what we are doing. Actually we're calling Runtime.exit() from within a shutdown hook which matches the conditions described above and causes indefinite blocking.

This got introduced with !99 (merged) and we discussed this here. I have the feeling it might not be the best idea after all to let the lifecycle manager exit the VM. Maybe it's better to let the individual starting points that use the lifecycle be responsible for that, i.e. the CLI, the Android app and the unit tests should handle that in some way that makes sense and works nicely in the respective scenario. I think a call to Runtime.exit() within the lifecycle manager is just a too drastic measure which is difficult to make work in all scenarios and we're making our life a lot harder by trying to make the starting points work around the fact that the lifecycle manager is calling exit() itself.

If we use the mailbox in integration tests, this will be a problem too, because the test frameworks cannot gracefully handle components that exit the VM either. I recently added an option to disable this exiting behavior on the branch for integration tests with briar: a488bb20 and if I pass false as exitAfterStopping in the CLI the exiting using CTRL+C also works as expected again. So maybe that is a middle ground where we can have the exiting in the lifecycle where we wanted it to be as a result of the discussion where it should be for the Android app, and yet still be able to disable this for both the CLI and integration tests.

Edited Aug 11, 2022 by Sebastian
Assignee
Assign to
Time tracking