staload UNSAFE = "prelude/SATS/unsafe.sats"
staload _ = "prelude/DATS/pointer.dats"
staload T = "libc/sys/SATS/types.sats"
macdef int_of_pid = $T.int_of_pid
staload "libc/SATS/errno.sats"
staload "libc/SATS/fcntl.sats"
staload "libc/SATS/signal.sats"
staload "libc/SATS/stdio.sats"
staload "libc/SATS/stdlib.sats"
staload "libc/SATS/unistd.sats"
fun try1 () = let
val pid = fork_err ()
val ipid = int_of_pid (pid)
in
case+ 0 of
| _ when ipid = 0 => let
val cpid = getpid ()
val () = printf ("try1: child(%ld)\n", @($UNSAFE.cast2lint(cpid)))
in
exit (EXIT_SUCCESS)
end | _ when ipid > 0 => let
val () = printf ("parent(%d)\n", @(ipid))
in
end | _ => let
val () = perror ("fork")
in
exit (EXIT_SUCCESS)
end end
fun try4 () = let
typedef T = sigset_t
var set: T
val err = sigemptyset (set)
val () = assertloc (err = 0)
prval () = opt_unsome{T} (set)
val err = sigaddset (set, SIGUSR1) val () = assertloc (err = 0)
val err = sigprocmask_null (SIG_SETMASK, set)
val pid = fork_err ()
val ipid = int_of_pid (pid)
in
case+ 0 of
| _ when ipid = 0 => let var act: sigaction
val () = ptr_zero<sigaction> (act)
val () = act.sa_handler := sighandler(lam (sgn:signum_t): void => ())
val err = sigaction_null (SIGUSR1, act)
val () = assertloc (err = 0)
var suspendset: sigset_t
val err = sigfillset (suspendset)
val () = assertloc (err = 0)
prval () = opt_unsome{T} (suspendset)
val err = sigdelset (suspendset, SIGUSR1) val () = assertloc (err = 0)
val err = sigsuspend (suspendset)
val () = assertloc (err < 0)
val () = if (errno_get() = EINTR) then let
val cpid = getpid ()
val () = printf ("try4: child(%ld)\n", @($UNSAFE.cast2lint(cpid)))
val () = exit (EXIT_SUCCESS)
in
end val () = exit (EXIT_FAILURE)
in
end | _ when ipid > 0 => let val () = printf ("parent(%d)\n", @(ipid))
val err = kill (pid, SIGUSR1)
val () = assertloc (err = 0)
in
end | _ => let
val () = perror "fork" in
end end
fun try5 () = let
var set: sigset_t
val err = sigemptyset (set)
val () = assertloc (err = 0)
prval () = opt_unsome{sigset_t} (set)
val err = sigaddset (set, SIGUSR1)
val () = assertloc (err = 0)
val err = sigprocmask_null (SIG_SETMASK, set)
val () = assertloc (err = 0)
val pid = fork_err ()
val ipid = int_of_pid (pid)
in
case+ 0 of
| _ when ipid = 0 => let var sgn: signum_t
val err = sigwait (set, sgn) val () = assertloc (err = 0)
prval () = opt_unsome{signum_t} (sgn)
val cpid = getpid ()
val () = printf ("try5: child(%ld)\n", @($UNSAFE.cast2lint(cpid)))
in
exit (EXIT_SUCCESS)
end | _ when ipid > 0 => let val () = printf ("parent(%d)\n", @(ipid))
val err = kill (pid, SIGUSR1)
val () = assertloc (err = 0)
in
end | _ => let
val () = perror "fork" in
end end
fun try6 () = let
var fd1: int and fd2: int
val (pfopt | err) = pipe (fd1, fd2)
val () = assertloc (err >= 0)
prval Some_v @(pfd1, pfd2) = pfopt
val pid = fork_err ()
val ipid = int_of_pid (pid)
in
case+ 0 of
| _ when ipid = 0 => let val () = close_exn (pfd2 | fd2)
var c: byte
prval pfc = array_v_sing (view@ c)
val nread = read_err (pfd1 | fd1, c, 1)
prval () = view@ c := array_v_unsing (pfc)
val () = close_exn (pfd1 | fd1)
val cpid = getpid ()
val () = printf ("try6: child(%ld)\n", @($UNSAFE.cast2lint(cpid)))
in
exit (EXIT_SUCCESS)
end | _ when ipid > 0 => let val () = printf ("parent(%d)\n", @(ipid))
val () = close_exn (pfd1 | fd1)
val () = close_exn (pfd2 | fd2)
in
end | _ => let val () = close_exn (pfd1 | fd1)
val () = close_exn (pfd2 | fd2)
val () = perror ("fork")
in
exit (EXIT_SUCCESS)
end end
implement
main () = () where {
val () = try1 ()
val () = try4 ()
val () = try5 ()
val () = try6 ()
val _leftover = sleep (1)
}