@@ -35,25 +35,31 @@ func Exit1WithMessage(message string) {
3535 os .Exit (1 )
3636}
3737
38- func ParseMonitorArgs ( args []string ) (* launchlib.ProcessMonitor , error ) {
38+ func CreateMonitorFromArgs ( primaryPID string , subPIDs []string ) (* launchlib.ProcessMonitor , error ) {
3939 monitor := & launchlib.ProcessMonitor {}
4040
4141 var err error
42- if monitor .PrimaryPID , err = strconv .Atoi (args [ 0 ] ); err != nil {
42+ if monitor .PrimaryPID , err = strconv .Atoi (primaryPID ); err != nil {
4343 return nil , errors .Wrapf (err , "error parsing service pid" )
4444 }
45- if monitor .ProcessGroupPID , err = strconv .Atoi (args [1 ]); err != nil {
46- return nil , errors .Wrapf (err , "error parsing service group id" )
45+
46+ for _ , pidStr := range subPIDs {
47+ pid , err := strconv .Atoi (pidStr )
48+ if err != nil {
49+ return nil , errors .Wrapf (err , "error parsing sub-process pid" )
50+ }
51+ monitor .SubProcessPIDs = append (monitor .SubProcessPIDs , pid )
4752 }
4853 return monitor , nil
4954}
5055
5156func GenerateMonitorArgs (monitor * launchlib.ProcessMonitor ) []string {
52- return []string {
53- monitorFlag ,
54- strconv . Itoa ( monitor .PrimaryPID ),
55- strconv .Itoa (monitor . ProcessGroupPID ),
57+ args := make ( []string , 0 , len ( monitor . SubProcessPIDs ) + 2 )
58+ args = append ( args , monitorFlag , strconv . Itoa ( monitor . PrimaryPID ))
59+ for _ , pid := range monitor .SubProcessPIDs {
60+ args = append ( args , strconv .Itoa (pid ))
5661 }
62+ return args
5763}
5864
5965func main () {
@@ -62,23 +68,27 @@ func main() {
6268 stdout := os .Stdout
6369
6470 switch numArgs := len (os .Args ); {
65- case numArgs == 4 && os .Args [1 ] == monitorFlag :
66- if monitor , err := ParseMonitorArgs (os .Args [2 :]); err != nil {
71+ case numArgs > 3 && os .Args [1 ] == monitorFlag :
72+ monitor , err := CreateMonitorFromArgs (os .Args [2 ], os .Args [3 :])
73+
74+ if err != nil {
6775 fmt .Println ("error parsing monitor args" , err )
68- Exit1WithMessage (fmt .Sprintf ("Usage: go-java-launcher %s <primary pid> <pgid>" , monitorFlag ))
69- } else if err = monitor .TermProcessGroupOnDeath (); err != nil {
76+ Exit1WithMessage (fmt .Sprintf ("Usage: go-java-launcher %s <primary pid> <sub-process pids...>" , monitorFlag ))
77+ }
78+
79+ if err = monitor .Run (); err != nil {
7080 fmt .Println ("error running process monitor" , err )
7181 Exit1WithMessage ("process monitor failed" )
7282 }
7383 return
74- case numArgs > 3 :
75- Exit1WithMessage ("Usage: go-java-launcher <path to PrimaryStaticLauncherConfig> " +
76- "[<path to PrimaryCustomLauncherConfig>]" )
7784 case numArgs == 2 :
7885 staticConfigFile = os .Args [1 ]
7986 case numArgs == 3 :
8087 staticConfigFile = os .Args [1 ]
8188 customConfigFile = os .Args [2 ]
89+ default :
90+ Exit1WithMessage ("Usage: go-java-launcher <path to PrimaryStaticLauncherConfig> " +
91+ "[<path to PrimaryCustomLauncherConfig>]" )
8292 }
8393
8494 // Read configuration
@@ -109,51 +119,43 @@ func main() {
109119 }
110120
111121 if len (cmds .SubProcesses ) != 0 {
112- // For this process (referenced as 0), set the process group id to our pid (also referenced as 0), to
113- // ensure we are in our own group.
114- if err := syscall .Setpgid (0 , 0 ); err != nil {
115- fmt .Printf ("Unable to create process group for primary with subProcesses" )
116- panic (err )
117- }
118-
119- pgid := syscall .Getpgrp ()
120122 monitor := & launchlib.ProcessMonitor {
121- PrimaryPID : os .Getpid (),
122- ProcessGroupPID : pgid ,
123- }
124- monitorCmd := exec .Command (os .Args [0 ], GenerateMonitorArgs (monitor )... )
125- monitorCmd .Stdout = os .Stdout
126- monitorCmd .Stderr = os .Stderr
127-
128- // From this point, if the launcher, or subsequent primary process dies, the process group will be
129- // terminated by the process monitor
130- fmt .Println ("Starting process monitor for service process group " , pgid )
131- if err := monitorCmd .Start (); err != nil {
132- fmt .Println ("Failed to start process monitor for service process group" )
133- panic (err )
123+ PrimaryPID : os .Getpid (),
124+ SubProcessPIDs : nil ,
134125 }
126+ // From this point, any errors in the launcher will cause all of the created sub-processes to also die,
127+ // once the main process is exec'ed, this defer will no longer apply, and the external monitor assumes
128+ // responsibility for killing the sub-processes.
129+ defer func () {
130+ if err := monitor .KillSubProcesses (); err != nil {
131+ // Defer only called if failure complete exec of the primary process, so already panicking
132+ fmt .Println ("error cleaning up sub-processes" , err )
133+ }
134+ }()
135135
136136 for name , subProcess := range cmds .SubProcesses {
137- // Create struct if not present, as to not override previously set SysProcAttr properties
138- if subProcess .SysProcAttr == nil {
139- subProcess .SysProcAttr = & syscall.SysProcAttr {}
140- }
141- // Do not set the pgid of the subProcesses, leaving them in the same process group as this one
142- subProcess .SysProcAttr .Setpgid = false
143137 subProcess .Stdout = os .Stdout
144138 subProcess .Stderr = os .Stderr
145139
146140 fmt .Println ("Starting subProcesses " , name , subProcess .Path )
147141 if execErr := subProcess .Start (); execErr != nil {
148142 if os .IsNotExist (execErr ) {
149- fmt .Printf ("Executable not found for subProcess %s at: %s\n " , name ,
150- subProcess .Path )
143+ fmt .Printf ("Executable not found for subProcess %s at: %s\n " , name , subProcess .Path )
151144 }
152145 panic (execErr )
153- } else {
154- fmt .Printf ("Started subProcess %s under process pid %d\n " , name ,
155- subProcess .Process .Pid )
156146 }
147+ monitor .SubProcessPIDs = append (monitor .SubProcessPIDs , subProcess .Process .Pid )
148+ fmt .Printf ("Started subProcess %s under process pid %d\n " , name , subProcess .Process .Pid )
149+ }
150+
151+ monitorCmd := exec .Command (os .Args [0 ], GenerateMonitorArgs (monitor )... )
152+ monitorCmd .Stdout = os .Stdout
153+ monitorCmd .Stderr = os .Stderr
154+
155+ fmt .Println ("Starting process monitor for service process " , monitor .PrimaryPID )
156+ if err := monitorCmd .Start (); err != nil {
157+ fmt .Println ("Failed to start process monitor for service process" )
158+ panic (err )
157159 }
158160 }
159161
0 commit comments