@@ -398,6 +398,8 @@ static void service_done(Unit *u) {
398398 s -> timer_event_source = sd_event_source_disable_unref (s -> timer_event_source );
399399 s -> exec_fd_event_source = sd_event_source_disable_unref (s -> exec_fd_event_source );
400400
401+ s -> bus_name_pid_lookup_slot = sd_bus_slot_unref (s -> bus_name_pid_lookup_slot );
402+
401403 service_release_resources (u );
402404}
403405
@@ -4322,6 +4324,60 @@ static int service_get_timeout(Unit *u, usec_t *timeout) {
43224324 return 1 ;
43234325}
43244326
4327+ static bool pick_up_pid_from_bus_name (Service * s ) {
4328+ assert (s );
4329+
4330+ /* If the service is running but we have no main PID yet, get it from the owner of the D-Bus name */
4331+
4332+ return !pid_is_valid (s -> main_pid ) &&
4333+ IN_SET (s -> state ,
4334+ SERVICE_START ,
4335+ SERVICE_START_POST ,
4336+ SERVICE_RUNNING ,
4337+ SERVICE_RELOAD );
4338+ }
4339+
4340+ static int bus_name_pid_lookup_callback (sd_bus_message * reply , void * userdata , sd_bus_error * ret_error ) {
4341+ const sd_bus_error * e ;
4342+ Unit * u = userdata ;
4343+ uint32_t pid ;
4344+ Service * s ;
4345+ int r ;
4346+
4347+ assert (reply );
4348+ assert (u );
4349+
4350+ s = SERVICE (u );
4351+ s -> bus_name_pid_lookup_slot = sd_bus_slot_unref (s -> bus_name_pid_lookup_slot );
4352+
4353+ if (!s -> bus_name || !pick_up_pid_from_bus_name (s ))
4354+ return 1 ;
4355+
4356+ e = sd_bus_message_get_error (reply );
4357+ if (e ) {
4358+ r = sd_bus_error_get_errno (e );
4359+ log_warning_errno (r , "GetConnectionUnixProcessID() failed: %s" , bus_error_message (e , r ));
4360+ return 1 ;
4361+ }
4362+
4363+ r = sd_bus_message_read (reply , "u" , & pid );
4364+ if (r < 0 ) {
4365+ bus_log_parse_error (r );
4366+ return 1 ;
4367+ }
4368+
4369+ if (!pid_is_valid (pid )) {
4370+ log_debug_errno (SYNTHETIC_ERRNO (EINVAL ), "GetConnectionUnixProcessID() returned invalid PID" );
4371+ return 1 ;
4372+ }
4373+
4374+ log_unit_debug (u , "D-Bus name %s is now owned by process " PID_FMT , s -> bus_name , (pid_t ) pid );
4375+
4376+ service_set_main_pid (s , pid );
4377+ unit_watch_pid (UNIT (s ), pid , false);
4378+ return 1 ;
4379+ }
4380+
43254381static void service_bus_name_owner_change (Unit * u , const char * new_owner ) {
43264382
43274383 Service * s = SERVICE (u );
@@ -4352,28 +4408,25 @@ static void service_bus_name_owner_change(Unit *u, const char *new_owner) {
43524408 else if (s -> state == SERVICE_START && new_owner )
43534409 service_enter_start_post (s );
43544410
4355- } else if (new_owner &&
4356- s -> main_pid <= 0 &&
4357- IN_SET (s -> state ,
4358- SERVICE_START ,
4359- SERVICE_START_POST ,
4360- SERVICE_RUNNING ,
4361- SERVICE_RELOAD )) {
4362-
4363- _cleanup_ (sd_bus_creds_unrefp ) sd_bus_creds * creds = NULL ;
4364- pid_t pid ;
4411+ } else if (new_owner && pick_up_pid_from_bus_name (s )) {
43654412
43664413 /* Try to acquire PID from bus service */
43674414
4368- r = sd_bus_get_name_creds (u -> manager -> api_bus , s -> bus_name , SD_BUS_CREDS_PID , & creds );
4369- if (r >= 0 )
4370- r = sd_bus_creds_get_pid (creds , & pid );
4371- if (r >= 0 ) {
4372- log_unit_debug (u , "D-Bus name %s is now owned by process " PID_FMT , s -> bus_name , pid );
4373-
4374- service_set_main_pid (s , pid );
4375- unit_watch_pid (UNIT (s ), pid , false);
4376- }
4415+ s -> bus_name_pid_lookup_slot = sd_bus_slot_unref (s -> bus_name_pid_lookup_slot );
4416+
4417+ r = sd_bus_call_method_async (
4418+ u -> manager -> api_bus ,
4419+ & s -> bus_name_pid_lookup_slot ,
4420+ "org.freedesktop.DBus" ,
4421+ "/org/freedesktop/DBus" ,
4422+ "org.freedesktop.DBus" ,
4423+ "GetConnectionUnixProcessID" ,
4424+ bus_name_pid_lookup_callback ,
4425+ s ,
4426+ "s" ,
4427+ s -> bus_name );
4428+ if (r < 0 )
4429+ log_debug_errno (r , "Failed to request owner PID of service name, ignoring: %m" );
43774430 }
43784431}
43794432
0 commit comments