@@ -21,7 +21,9 @@ import (
2121 "fmt"
2222 "log"
2323 "os"
24+ "os/signal"
2425 "strings"
26+ "syscall"
2527
2628 "github.com/ctrox/csi-s3/pkg/driver"
2729)
5052func main () {
5153 flag .Parse ()
5254
55+ // We're running in the container as PID-1 which gets some special
56+ // treatment by the kernel. In particular, if a process in the container
57+ // terminates and there are still active child processes, the kernel will move
58+ // those orphaned processes to be child processes of PID-1 and signal it
59+ // by sending a SIGCHLD. Init-systems are expected to handle this case by
60+ // reaping those "orphan" processes once they exit.
61+ //
62+ // Since all available mounters are instructed to daemonize, we need to reap
63+ // the daemonized processes since their parent (the mounter) exists once the daemon
64+ // is running.
65+ go func () {
66+ ch := make (chan os.Signal , 1 )
67+
68+ signal .Notify (ch , syscall .SIGCHLD )
69+
70+ for range ch {
71+ var status syscall.WaitStatus
72+ pid , err := syscall .Wait4 (- 1 , & status , 0 , nil )
73+ if err != nil {
74+ // we might receive ECHILD when the mounter exits after daemonizing.
75+ // We'll be late calling Wait4 here as that process is already reaped
76+ // since we're using exec.Command().Run() which already calls Waitpid
77+ if val , ok := err .(syscall.Errno ); ! ok || val != syscall .ECHILD {
78+ log .Printf ("failed to call wait4: %s\n " , err )
79+ }
80+
81+ } else {
82+ log .Printf ("repeated child %d: status=%d\n " , pid , status .ExitStatus ())
83+ }
84+ }
85+ }()
86+
5387 driver , err := driver .New (* nodeID , * endpoint , segments )
5488 if err != nil {
5589 log .Fatal (err )
0 commit comments