3535static const UnitActiveState state_translation_table [_SCOPE_STATE_MAX ] = {
3636 [SCOPE_DEAD ] = UNIT_INACTIVE ,
3737 [SCOPE_RUNNING ] = UNIT_ACTIVE ,
38+ [SCOPE_ABANDONED ] = UNIT_ACTIVE ,
3839 [SCOPE_STOP_SIGTERM ] = UNIT_DEACTIVATING ,
3940 [SCOPE_STOP_SIGKILL ] = UNIT_DEACTIVATING ,
4041 [SCOPE_FAILED ] = UNIT_FAILED
@@ -66,9 +67,6 @@ static void scope_done(Unit *u) {
6667
6768 free (s -> controller );
6869
69- set_free (s -> pids );
70- s -> pids = NULL ;
71-
7270 s -> timer_event_source = sd_event_source_unref (s -> timer_event_source );
7371}
7472
@@ -100,15 +98,14 @@ static void scope_set_state(Scope *s, ScopeState state) {
10098 old_state = s -> state ;
10199 s -> state = state ;
102100
103- if (state != SCOPE_STOP_SIGTERM &&
104- state != SCOPE_STOP_SIGKILL )
101+ if (!IN_SET (state , SCOPE_STOP_SIGTERM , SCOPE_STOP_SIGKILL ))
105102 s -> timer_event_source = sd_event_source_unref (s -> timer_event_source );
106103
104+ if (IN_SET (state , SCOPE_DEAD , SCOPE_FAILED ))
105+ unit_unwatch_all_pids (UNIT (s ));
106+
107107 if (state != old_state )
108- log_debug ("%s changed %s -> %s" ,
109- UNIT (s )-> id ,
110- scope_state_to_string (old_state ),
111- scope_state_to_string (state ));
108+ log_debug ("%s changed %s -> %s" , UNIT (s )-> id , scope_state_to_string (old_state ), scope_state_to_string (state ));
112109
113110 unit_notify (UNIT (s ), state_translation_table [old_state ], state_translation_table [state ], true);
114111}
@@ -135,7 +132,7 @@ static int scope_verify(Scope *s) {
135132 if (UNIT (s )-> load_state != UNIT_LOADED )
136133 return 0 ;
137134
138- if (set_size ( s -> pids ) <= 0 && UNIT (s )-> manager -> n_reloading <= 0 ) {
135+ if (set_isempty ( UNIT ( s ) -> pids ) && UNIT (s )-> manager -> n_reloading <= 0 ) {
139136 log_error_unit (UNIT (s )-> id , "Scope %s has no PIDs. Refusing." , UNIT (s )-> id );
140137 return - EINVAL ;
141138 }
@@ -181,12 +178,15 @@ static int scope_coldplug(Unit *u) {
181178
182179 if (s -> deserialized_state != s -> state ) {
183180
184- if (s -> deserialized_state == SCOPE_STOP_SIGKILL || s -> deserialized_state == SCOPE_STOP_SIGTERM ) {
181+ if (IN_SET ( s -> deserialized_state , SCOPE_STOP_SIGKILL , SCOPE_STOP_SIGTERM ) ) {
185182 r = scope_arm_timer (s );
186183 if (r < 0 )
187184 return r ;
188185 }
189186
187+ if (!IN_SET (s -> deserialized_state , SCOPE_DEAD , SCOPE_FAILED ))
188+ unit_watch_all_pids (UNIT (s ));
189+
190190 scope_set_state (s , s -> deserialized_state );
191191 }
192192
@@ -227,6 +227,8 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
227227 if (f != SCOPE_SUCCESS )
228228 s -> result = f ;
229229
230+ unit_watch_all_pids (UNIT (s ));
231+
230232 /* If we have a controller set let's ask the controller nicely
231233 * to terminate the scope, instead of us going directly into
232234 * SIGTERM beserk mode */
@@ -288,13 +290,10 @@ static int scope_start(Unit *u) {
288290 return r ;
289291 }
290292
291- r = cg_attach_many_everywhere (u -> manager -> cgroup_supported , u -> cgroup_path , s -> pids );
293+ r = cg_attach_many_everywhere (u -> manager -> cgroup_supported , u -> cgroup_path , UNIT ( s ) -> pids );
292294 if (r < 0 )
293295 return r ;
294296
295- set_free (s -> pids );
296- s -> pids = NULL ;
297-
298297 s -> result = SCOPE_SUCCESS ;
299298
300299 scope_set_state (s , SCOPE_RUNNING );
@@ -305,13 +304,13 @@ static int scope_stop(Unit *u) {
305304 Scope * s = SCOPE (u );
306305
307306 assert (s );
308- assert (s -> state == SCOPE_RUNNING );
309307
310308 if (s -> state == SCOPE_STOP_SIGTERM ||
311309 s -> state == SCOPE_STOP_SIGKILL )
312310 return 0 ;
313311
314- assert (s -> state == SCOPE_RUNNING );
312+ assert (s -> state == SCOPE_RUNNING ||
313+ s -> state == SCOPE_ABANDONED );
315314
316315 scope_enter_signal (s , SCOPE_STOP_SIGTERM , SCOPE_SUCCESS );
317316 return 0 ;
@@ -389,15 +388,41 @@ static bool scope_check_gc(Unit *u) {
389388 /* Never clean up scopes that still have a process around,
390389 * even if the scope is formally dead. */
391390
392- if (UNIT ( s ) -> cgroup_path ) {
393- r = cg_is_empty_recursive (SYSTEMD_CGROUP_CONTROLLER , UNIT ( s ) -> cgroup_path , true);
391+ if (u -> cgroup_path ) {
392+ r = cg_is_empty_recursive (SYSTEMD_CGROUP_CONTROLLER , u -> cgroup_path , true);
394393 if (r <= 0 )
395394 return true;
396395 }
397396
398397 return false;
399398}
400399
400+ static void scope_notify_cgroup_empty_event (Unit * u ) {
401+ Scope * s = SCOPE (u );
402+ assert (u );
403+
404+ log_debug_unit (u -> id , "%s: cgroup is empty" , u -> id );
405+
406+ if (IN_SET (s -> state , SCOPE_RUNNING , SCOPE_ABANDONED , SCOPE_STOP_SIGTERM , SCOPE_STOP_SIGKILL ))
407+ scope_enter_dead (s , SCOPE_SUCCESS );
408+ }
409+
410+ static void scope_sigchld_event (Unit * u , pid_t pid , int code , int status ) {
411+
412+ /* If we get a SIGCHLD event for one of the processes we were
413+ interested in, then we look for others to watch, under the
414+ assumption that we'll sooner or later get a SIGCHLD for
415+ them, as the original process we watched was probably the
416+ parent of them, and they are hence now our children. */
417+
418+ unit_tidy_watch_pids (u , 0 , 0 );
419+ unit_watch_all_pids (u );
420+
421+ /* If the PID set is empty now, then let's finish this off */
422+ if (set_isempty (u -> pids ))
423+ scope_notify_cgroup_empty_event (u );
424+ }
425+
401426static int scope_dispatch_timer (sd_event_source * source , usec_t usec , void * userdata ) {
402427 Scope * s = SCOPE (userdata );
403428
@@ -429,24 +454,30 @@ static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *user
429454 return 0 ;
430455}
431456
432- static void scope_notify_cgroup_empty_event (Unit * u ) {
433- Scope * s = SCOPE (u );
434- assert (u );
457+ int scope_abandon (Scope * s ) {
458+ assert (s );
435459
436- log_debug_unit (u -> id , "%s: cgroup is empty" , u -> id );
460+ if (!IN_SET (s -> state , SCOPE_RUNNING , SCOPE_ABANDONED ))
461+ return - ESTALE ;
437462
438- switch (s -> state ) {
463+ free (s -> controller );
464+ s -> controller = NULL ;
439465
440- case SCOPE_RUNNING :
441- case SCOPE_STOP_SIGTERM :
442- case SCOPE_STOP_SIGKILL :
443- scope_enter_dead ( s , SCOPE_SUCCESS );
466+ /* The client is no longer watching the remaining processes,
467+ * so let's step in here, under the assumption that the
468+ * remaining processes will be sooner or later reassigned to
469+ * us as parent. */
444470
445- break ;
471+ unit_tidy_watch_pids (UNIT (s ), 0 , 0 );
472+ unit_watch_all_pids (UNIT (s ));
446473
447- default :
448- ;
449- }
474+ /* If the PID set is empty now, then let's finish this off */
475+ if (set_isempty (UNIT (s )-> pids ))
476+ scope_notify_cgroup_empty_event (UNIT (s ));
477+ else
478+ scope_set_state (s , SCOPE_ABANDONED );
479+
480+ return 0 ;
450481}
451482
452483_pure_ static UnitActiveState scope_active_state (Unit * u ) {
@@ -464,6 +495,7 @@ _pure_ static const char *scope_sub_state_to_string(Unit *u) {
464495static const char * const scope_state_table [_SCOPE_STATE_MAX ] = {
465496 [SCOPE_DEAD ] = "dead" ,
466497 [SCOPE_RUNNING ] = "running" ,
498+ [SCOPE_ABANDONED ] = "abandoned" ,
467499 [SCOPE_STOP_SIGTERM ] = "stop-sigterm" ,
468500 [SCOPE_STOP_SIGKILL ] = "stop-sigkill" ,
469501 [SCOPE_FAILED ] = "failed" ,
@@ -516,6 +548,8 @@ const UnitVTable scope_vtable = {
516548
517549 .check_gc = scope_check_gc ,
518550
551+ .sigchld_event = scope_sigchld_event ,
552+
519553 .reset_failed = scope_reset_failed ,
520554
521555 .notify_cgroup_empty = scope_notify_cgroup_empty_event ,
0 commit comments