Skip to content
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

Doing cleanup in MirageOS when tender shuts down unikernel #1355

Open
rand00 opened this issue Sep 14, 2022 · 2 comments
Open

Doing cleanup in MirageOS when tender shuts down unikernel #1355

rand00 opened this issue Sep 14, 2022 · 2 comments

Comments

@rand00
Copy link

rand00 commented Sep 14, 2022

After some discussion with @hannesm it doesn't seem like there is a consistent story of how to do cleanup in a unikernel when it's not an exception that is thrown, but the tender that exits the unikernel.

In my usecase, I was surprised that Mirage_runtime.at_exit didn't run to cleanup my TCP flow, in the case where I Ctrl-c the solo5-spt <unikernel>.

Could Mirage_runtime.at_exit run on any kind of exit?

@reynir
Copy link
Member

reynir commented Sep 14, 2022

I looked into the code, and the function registered by at_exit are actually called. https://github.com/mirage/mirage-solo5/blob/main/lib/main.ml#L72-L75

What you're observing could maybe be explained by the call to Lwt.abandon_wakeups - maybe some lwt tasks necessary for actually sending FIN is cancelled and the packet is never sent.

It can also be observed with the following slightly modified mirage-skeleton/tutorial/hello unikernel:

open Lwt.Infix

module Hello (Time : Mirage_time.S) = struct
  let at_exit () =
    Logs.warn (fun f -> f "Oh no, we're exiting!");
    Lwt.return_unit

  let start _time =
    Mirage_runtime.at_exit at_exit;
    let rec loop = function
      | 0 -> Lwt.return_unit
      | n ->
          Logs.info (fun f -> f "hello");
          Time.sleep_ns (Duration.of_sec 1) >>= fun () -> loop (n - 1)
    in
    loop 4
end
$ mirage configure -t && make
...
$ $ solo5-hvt -- dist/hello.hvt 
            |      ___|
  __|  _ \  |  _ \ __ \
\__ \ (   | | (   |  ) |
____/\___/ _|\___/____/
Solo5: Bindings version v0.7.3
Solo5: Memory map: 512 MB addressable:
Solo5:   reserved @ (0x0 - 0xfffff)
Solo5:       text @ (0x100000 - 0x1dffff)
Solo5:     rodata @ (0x1e0000 - 0x215fff)
Solo5:       data @ (0x216000 - 0x2c0fff)
Solo5:       heap >= 0x2c1000 < stack < 0x20000000
2022-09-14 17:39:32 -00:00: INF [application] hello
2022-09-14 17:39:33 -00:00: INF [application] hello
2022-09-14 17:39:34 -00:00: INF [application] hello
2022-09-14 17:39:35 -00:00: INF [application] hello
2022-09-14 17:39:36 -00:00: WRN [application] Oh no, we're exiting!
Solo5: solo5_exit(0) called

@reynir
Copy link
Member

reynir commented Sep 15, 2022

On testing with ctrl-c it does indeed seem to not run the exit handlers on solo5-hvt

$ solo5-hvt -- dist/hello.hvt 
            |      ___|
  __|  _ \  |  _ \ __ \
\__ \ (   | | (   |  ) |
____/\___/ _|\___/____/
Solo5: Bindings version v0.7.3
Solo5: Memory map: 512 MB addressable:
Solo5:   reserved @ (0x0 - 0xfffff)
Solo5:       text @ (0x100000 - 0x1dffff)
Solo5:     rodata @ (0x1e0000 - 0x215fff)
Solo5:       data @ (0x216000 - 0x2c0fff)
Solo5:       heap >= 0x2c1000 < stack < 0x20000000
2022-09-15 06:05:19 -00:00: INF [application] hello
2022-09-15 06:05:20 -00:00: INF [application] hello
^Csolo5-hvt: Exiting on signal 2

And indeed, the man page for atexit(3) says

Functions registered using atexit() (and on_exit(3)) are not called if a process terminates abnormally because of the delivery of a signal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants