@@ -870,14 +870,7 @@ func NewSystemd(slice, group string, pid int, resources *Resources) (*Manager, e
870870 newSystemdProperty ("TasksMax" , uint64 (resources .Pids .Max )))
871871 }
872872
873- statusChan := make (chan string , 1 )
874- if _ , err := conn .StartTransientUnitContext (ctx , group , "replace" , properties , statusChan ); err == nil {
875- select {
876- case <- statusChan :
877- case <- time .After (time .Second ):
878- logrus .Warnf ("Timed out while waiting for StartTransientUnit(%s) completion signal from dbus. Continuing..." , group )
879- }
880- } else if ! isUnitExists (err ) {
873+ if err := startUnit (conn , group , properties , pid == - 1 ); err != nil {
881874 return & Manager {}, err
882875 }
883876
@@ -886,6 +879,60 @@ func NewSystemd(slice, group string, pid int, resources *Resources) (*Manager, e
886879 }, nil
887880}
888881
882+ func startUnit (conn * systemdDbus.Conn , group string , properties []systemdDbus.Property , ignoreExists bool ) error {
883+ ctx := context .TODO ()
884+
885+ statusChan := make (chan string , 1 )
886+ defer close (statusChan )
887+
888+ retry := true
889+ started := false
890+
891+ for ! started {
892+ if _ , err := conn .StartTransientUnitContext (ctx , group , "replace" , properties , statusChan ); err != nil {
893+ if ! isUnitExists (err ) {
894+ return err
895+ }
896+
897+ if ignoreExists {
898+ return nil
899+ }
900+
901+ if retry {
902+ retry = false
903+ // When a unit of the same name already exists, it may be a leftover failed unit.
904+ // If we reset it once, systemd can try to remove it.
905+ attemptFailedUnitReset (conn , group )
906+ continue
907+ }
908+
909+ return err
910+ } else {
911+ started = true
912+ }
913+ }
914+
915+ select {
916+ case s := <- statusChan :
917+ if s != "done" {
918+ attemptFailedUnitReset (conn , group )
919+ return fmt .Errorf ("error creating systemd unit `%s`: got `%s`" , group , s )
920+ }
921+ case <- time .After (30 * time .Second ):
922+ logrus .Warnf ("Timed out while waiting for StartTransientUnit(%s) completion signal from dbus. Continuing..." , group )
923+ }
924+
925+ return nil
926+ }
927+
928+ func attemptFailedUnitReset (conn * systemdDbus.Conn , group string ) {
929+ err := conn .ResetFailedUnitContext (context .TODO (), group )
930+
931+ if err != nil {
932+ logrus .Warnf ("Unable to reset failed unit: %v" , err )
933+ }
934+ }
935+
889936func LoadSystemd (slice , group string ) (* Manager , error ) {
890937 if slice == "" {
891938 slice = defaultSlice
0 commit comments