Files
linuxkit/projects/miragesdk/src/fdd/init.ml
Thomas Gazagnaire 56229e486b sdk: add a file-descriptor sharing server
```
$ fdd init &
$ fdd share /tmp/foo # serve a fresh socketpair on that path
$ fdd test /tmp/foo  # read the socketpair and test that it works
```

Instead of `fdd test` (which is only useful for testing), users are expected to
connect to the unix domain socket and call `recvmsg(2)`. They will get one side
of the socketpair. Two different processes can do this and they will be able to
talk to each other.

Signed-off-by: Thomas Gazagnaire <thomas@gazagnaire.org>
2017-06-29 17:53:49 +02:00

62 lines
1.7 KiB
OCaml

open Lwt.Infix
open Common
let src = Logs.Src.create "fdd/init"
module Log = (val Logs.src_log src : Logs.LOG)
let write_pid socket =
let pid_file = Filename.chop_extension socket ^ ".pid" in
if Sys.file_exists pid_file then (
Fmt.pr "Cannot start, as %s already exists.\n%!" pid_file;
exit 1
);
Lwt_unix.openfile pid_file Lwt_unix.[O_CREAT; O_EXCL] 0o644 >>= fun fd ->
Log.info (fun l -> l "Writing %s" pid_file);
let oc = Lwt_io.of_fd ~mode:Lwt_io.Output fd in
Lwt_io.write_line oc (string_of_int (Unix.getpid ())) >>= fun () ->
Lwt_io.close oc >|= fun () ->
at_exit (fun () ->
Log.info (fun l -> l "Removing %s" pid_file);
Unix.unlink pid_file
)
(* listen on fd and send the socketpair to the first 2 connections.*)
let send_socketpair fd =
let f, d = Lwt_unix.(socketpair PF_UNIX SOCK_STREAM 0) in
let send to_send =
Lwt_unix.accept fd >>= fun (fd, _) ->
Log.info (fun l -> l "New client!");
send_fd ~to_send fd
in
Lwt_unix.listen fd 2;
Lwt.join [send f; send d]
let recv_path fd =
let ic = Lwt_io.of_fd ~mode:Lwt_io.Input fd in
Lwt_io.read_line ic >>= fun line ->
let path = String.trim line in
bind path >>= fun fd ->
send_socketpair fd >>= fun () ->
Lwt_unix.unlink path
let listen fd =
let rec loop () =
Lwt_unix.accept fd >>= fun (fd, _) ->
Log.debug (fun l -> l "New client connected!");
Lwt.async (fun () ->
Lwt.catch
(fun () -> recv_path fd)
(fun e ->
Log.err (fun l -> l "asynchronous exn: %a" Fmt.exn e);
Lwt.return ())
);
loop ()
in
Lwt_unix.listen fd 10;
loop ()
let f socket =
write_pid socket >>= fun () ->
bind socket >>= fun fd ->
listen fd