2010-08-14 19:59:25 +02:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2010-01-23 01:52:57 +01:00
2010-02-03 13:03:47 +01:00
/***
This file is part of systemd .
Copyright 2010 Lennart Poettering
systemd is free software ; you can redistribute it and / or modify it
2012-04-12 00:20:58 +02:00
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
2010-02-03 13:03:47 +01:00
( at your option ) any later version .
systemd is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
2012-04-12 00:20:58 +02:00
Lesser General Public License for more details .
2010-02-03 13:03:47 +01:00
2012-04-12 00:20:58 +02:00
You should have received a copy of the GNU Lesser General Public License
2010-02-03 13:03:47 +01:00
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2010-01-23 01:52:57 +01:00
# include <errno.h>
2010-01-26 04:18:44 +01:00
# include <signal.h>
2010-02-14 01:09:01 +01:00
# include <unistd.h>
2010-01-23 01:52:57 +01:00
2014-05-13 23:22:13 +02:00
# include "async.h"
2012-02-09 13:05:23 +01:00
# include "manager.h"
2010-01-26 21:39:06 +01:00
# include "unit.h"
2010-01-23 01:52:57 +01:00
# include "service.h"
# include "load-fragment.h"
# include "load-dropin.h"
2010-01-26 04:18:44 +01:00
# include "log.h"
2010-02-14 01:09:01 +01:00
# include "strv.h"
2010-04-15 03:11:11 +02:00
# include "unit-name.h"
2012-09-18 11:27:56 +02:00
# include "unit-printf.h"
2010-04-18 03:08:16 +02:00
# include "dbus-service.h"
2010-06-18 04:22:59 +02:00
# include "special.h"
2011-01-20 18:22:03 +01:00
# include "exit-status.h"
2011-03-17 04:02:35 +01:00
# include "def.h"
2012-05-07 21:36:12 +02:00
# include "path-util.h"
2011-03-17 04:02:35 +01:00
# include "util.h"
2012-03-12 22:22:16 +01:00
# include "utf8.h"
2013-02-11 03:46:08 +01:00
# include "env-util.h"
2013-02-14 12:26:13 +01:00
# include "fileio.h"
2013-11-19 21:12:59 +01:00
# include "bus-error.h"
# include "bus-util.h"
2014-08-22 19:02:03 +02:00
# include "bus-kernel.h"
2010-01-26 04:18:44 +01:00
2010-01-27 04:31:52 +01:00
static const UnitActiveState state_translation_table [ _SERVICE_STATE_MAX ] = {
2010-01-26 21:39:06 +01:00
[ SERVICE_DEAD ] = UNIT_INACTIVE ,
[ SERVICE_START_PRE ] = UNIT_ACTIVATING ,
[ SERVICE_START ] = UNIT_ACTIVATING ,
[ SERVICE_START_POST ] = UNIT_ACTIVATING ,
[ SERVICE_RUNNING ] = UNIT_ACTIVE ,
2010-04-13 02:06:27 +02:00
[ SERVICE_EXITED ] = UNIT_ACTIVE ,
2010-07-01 03:34:15 +02:00
[ SERVICE_RELOAD ] = UNIT_RELOADING ,
2010-01-26 21:39:06 +01:00
[ SERVICE_STOP ] = UNIT_DEACTIVATING ,
2014-10-28 16:35:40 +01:00
[ SERVICE_STOP_SIGABRT ] = UNIT_DEACTIVATING ,
2010-01-26 21:39:06 +01:00
[ SERVICE_STOP_SIGTERM ] = UNIT_DEACTIVATING ,
[ SERVICE_STOP_SIGKILL ] = UNIT_DEACTIVATING ,
[ SERVICE_STOP_POST ] = UNIT_DEACTIVATING ,
[ SERVICE_FINAL_SIGTERM ] = UNIT_DEACTIVATING ,
[ SERVICE_FINAL_SIGKILL ] = UNIT_DEACTIVATING ,
2010-08-31 00:23:34 +02:00
[ SERVICE_FAILED ] = UNIT_FAILED ,
2010-07-01 00:31:53 +02:00
[ SERVICE_AUTO_RESTART ] = UNIT_ACTIVATING
2010-01-26 04:18:44 +01:00
} ;
2010-01-23 01:52:57 +01:00
2012-05-24 02:22:35 +02:00
/* For Type=idle we never want to delay any other jobs, hence we
* consider idle jobs active as soon as we start working on them */
static const UnitActiveState state_translation_table_idle [ _SERVICE_STATE_MAX ] = {
[ SERVICE_DEAD ] = UNIT_INACTIVE ,
[ SERVICE_START_PRE ] = UNIT_ACTIVE ,
[ SERVICE_START ] = UNIT_ACTIVE ,
[ SERVICE_START_POST ] = UNIT_ACTIVE ,
[ SERVICE_RUNNING ] = UNIT_ACTIVE ,
[ SERVICE_EXITED ] = UNIT_ACTIVE ,
[ SERVICE_RELOAD ] = UNIT_RELOADING ,
[ SERVICE_STOP ] = UNIT_DEACTIVATING ,
2014-10-28 16:35:40 +01:00
[ SERVICE_STOP_SIGABRT ] = UNIT_DEACTIVATING ,
2012-05-24 02:22:35 +02:00
[ SERVICE_STOP_SIGTERM ] = UNIT_DEACTIVATING ,
[ SERVICE_STOP_SIGKILL ] = UNIT_DEACTIVATING ,
[ SERVICE_STOP_POST ] = UNIT_DEACTIVATING ,
[ SERVICE_FINAL_SIGTERM ] = UNIT_DEACTIVATING ,
[ SERVICE_FINAL_SIGKILL ] = UNIT_DEACTIVATING ,
[ SERVICE_FAILED ] = UNIT_FAILED ,
[ SERVICE_AUTO_RESTART ] = UNIT_ACTIVATING
} ;
2013-11-19 21:12:59 +01:00
static int service_dispatch_io ( sd_event_source * source , int fd , uint32_t events , void * userdata ) ;
static int service_dispatch_timer ( sd_event_source * source , usec_t usec , void * userdata ) ;
static int service_dispatch_watchdog ( sd_event_source * source , usec_t usec , void * userdata ) ;
2013-12-11 20:49:43 +01:00
static void service_enter_signal ( Service * s , ServiceState state , ServiceResult f ) ;
2014-08-21 17:03:15 +02:00
static void service_enter_reload_by_notify ( Service * s ) ;
2013-12-11 20:49:43 +01:00
2010-04-21 03:27:44 +02:00
static void service_init ( Unit * u ) {
Service * s = SERVICE ( u ) ;
assert ( u ) ;
2012-01-15 12:04:08 +01:00
assert ( u - > load_state = = UNIT_STUB ) ;
2010-04-21 03:27:44 +02:00
2013-11-04 17:47:43 +01:00
s - > timeout_start_usec = u - > manager - > default_timeout_start_usec ;
s - > timeout_stop_usec = u - > manager - > default_timeout_stop_usec ;
s - > restart_usec = u - > manager - > default_restart_usec ;
2012-05-03 14:46:29 +02:00
s - > type = _SERVICE_TYPE_INVALID ;
2010-04-21 03:27:44 +02:00
s - > socket_fd = - 1 ;
2014-08-22 19:02:03 +02:00
s - > bus_endpoint_fd = - 1 ;
2011-02-13 18:51:30 +01:00
s - > guess_main_pid = true ;
2010-04-21 03:27:44 +02:00
2014-02-24 23:50:10 +01:00
RATELIMIT_INIT ( s - > start_limit , u - > manager - > default_start_limit_interval , u - > manager - > default_start_limit_burst ) ;
2010-04-21 03:27:44 +02:00
s - > control_command_id = _SERVICE_EXEC_COMMAND_INVALID ;
}
2010-04-11 00:22:36 +02:00
static void service_unwatch_control_pid ( Service * s ) {
assert ( s ) ;
if ( s - > control_pid < = 0 )
return ;
unit_unwatch_pid ( UNIT ( s ) , s - > control_pid ) ;
s - > control_pid = 0 ;
}
static void service_unwatch_main_pid ( Service * s ) {
assert ( s ) ;
if ( s - > main_pid < = 0 )
return ;
unit_unwatch_pid ( UNIT ( s ) , s - > main_pid ) ;
s - > main_pid = 0 ;
}
2012-01-19 23:58:07 +01:00
static void service_unwatch_pid_file ( Service * s ) {
if ( ! s - > pid_file_pathspec )
return ;
2014-11-27 20:20:23 +01:00
log_unit_debug ( UNIT ( s ) - > id , " Stopping watch for %s's PID file %s " , UNIT ( s ) - > id , s - > pid_file_pathspec - > path ) ;
2013-11-19 21:12:59 +01:00
path_spec_unwatch ( s - > pid_file_pathspec ) ;
2012-01-19 23:58:07 +01:00
path_spec_done ( s - > pid_file_pathspec ) ;
free ( s - > pid_file_pathspec ) ;
s - > pid_file_pathspec = NULL ;
}
2010-06-17 22:55:53 +02:00
static int service_set_main_pid ( Service * s , pid_t pid ) {
2010-06-18 22:05:29 +02:00
pid_t ppid ;
2010-06-17 22:55:53 +02:00
assert ( s ) ;
if ( pid < = 1 )
return - EINVAL ;
if ( pid = = getpid ( ) )
return - EINVAL ;
2013-10-01 05:06:56 +02:00
if ( s - > main_pid = = pid & & s - > main_pid_known )
return 0 ;
if ( s - > main_pid ! = pid ) {
service_unwatch_main_pid ( s ) ;
exec_status_start ( & s - > main_exec_status , pid ) ;
}
2013-08-09 16:40:57 +02:00
2011-04-28 04:56:53 +02:00
s - > main_pid = pid ;
s - > main_pid_known = true ;
if ( get_parent_of_pid ( pid , & ppid ) > = 0 & & ppid ! = getpid ( ) ) {
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s: Supervising process " PID_FMT " which is not our child. We'll most likely not notice when it exits. " , UNIT ( s ) - > id , pid ) ;
2011-04-28 04:56:53 +02:00
s - > main_pid_alien = true ;
} else
s - > main_pid_alien = false ;
2010-06-17 22:55:53 +02:00
return 0 ;
}
2010-04-15 06:19:54 +02:00
static void service_close_socket_fd ( Service * s ) {
assert ( s ) ;
2014-05-13 23:22:13 +02:00
s - > socket_fd = asynchronous_close ( s - > socket_fd ) ;
2010-04-15 06:19:54 +02:00
}
2010-06-19 04:25:28 +02:00
static void service_connection_unref ( Service * s ) {
assert ( s ) ;
2013-06-20 03:45:08 +02:00
if ( ! UNIT_ISSET ( s - > accept_socket ) )
2010-06-19 04:25:28 +02:00
return ;
2012-01-06 23:08:54 +01:00
socket_connection_unref ( SOCKET ( UNIT_DEREF ( s - > accept_socket ) ) ) ;
unit_ref_unset ( & s - > accept_socket ) ;
2010-06-19 04:25:28 +02:00
}
2012-02-01 17:17:12 +01:00
static void service_stop_watchdog ( Service * s ) {
assert ( s ) ;
2013-11-19 21:12:59 +01:00
s - > watchdog_event_source = sd_event_source_unref ( s - > watchdog_event_source ) ;
2013-12-11 20:49:43 +01:00
s - > watchdog_timestamp = DUAL_TIMESTAMP_NULL ;
2012-02-01 17:17:12 +01:00
}
2013-12-11 20:49:43 +01:00
static void service_start_watchdog ( Service * s ) {
2012-02-08 10:10:34 +01:00
int r ;
assert ( s ) ;
2013-12-11 20:49:43 +01:00
if ( s - > watchdog_usec < = 0 )
2012-02-08 10:10:34 +01:00
return ;
2013-11-19 21:12:59 +01:00
if ( s - > watchdog_event_source ) {
r = sd_event_source_set_time ( s - > watchdog_event_source , s - > watchdog_timestamp . monotonic + s - > watchdog_usec ) ;
if ( r < 0 ) {
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to reset watchdog timer: %m " , UNIT ( s ) - > id ) ;
2013-11-19 21:12:59 +01:00
return ;
}
2013-12-11 20:49:43 +01:00
r = sd_event_source_set_enabled ( s - > watchdog_event_source , SD_EVENT_ONESHOT ) ;
2013-12-12 20:16:06 +01:00
} else {
2014-03-24 02:49:09 +01:00
r = sd_event_add_time (
UNIT ( s ) - > manager - > event ,
& s - > watchdog_event_source ,
CLOCK_MONOTONIC ,
s - > watchdog_timestamp . monotonic + s - > watchdog_usec , 0 ,
service_dispatch_watchdog , s ) ;
2013-12-12 20:16:06 +01:00
if ( r < 0 ) {
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to add watchdog timer: %m " , UNIT ( s ) - > id ) ;
2013-12-12 20:16:06 +01:00
return ;
}
/* Let's process everything else which might be a sign
* of living before we consider a service died . */
r = sd_event_source_set_priority ( s - > watchdog_event_source , SD_EVENT_PRIORITY_IDLE ) ;
}
2013-11-19 21:12:59 +01:00
2012-02-08 10:10:34 +01:00
if ( r < 0 )
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to install watchdog timer: %m " , UNIT ( s ) - > id ) ;
2012-02-08 10:10:34 +01:00
}
2012-02-01 17:17:12 +01:00
static void service_reset_watchdog ( Service * s ) {
assert ( s ) ;
dual_timestamp_get ( & s - > watchdog_timestamp ) ;
2013-12-11 20:49:43 +01:00
service_start_watchdog ( s ) ;
2012-02-01 17:17:12 +01:00
}
2015-01-06 00:26:25 +01:00
static void service_fd_store_unlink ( ServiceFDStore * fs ) {
if ( ! fs )
return ;
if ( fs - > service ) {
assert ( fs - > service - > n_fd_store > 0 ) ;
LIST_REMOVE ( fd_store , fs - > service - > fd_store , fs ) ;
fs - > service - > n_fd_store - - ;
}
if ( fs - > event_source ) {
sd_event_source_set_enabled ( fs - > event_source , SD_EVENT_OFF ) ;
sd_event_source_unref ( fs - > event_source ) ;
}
safe_close ( fs - > fd ) ;
free ( fs ) ;
}
static void service_release_resources ( Unit * u ) {
Service * s = SERVICE ( u ) ;
assert ( s ) ;
if ( ! s - > fd_store )
return ;
log_debug ( " Releasing all resources for %s " , u - > id ) ;
while ( s - > fd_store )
service_fd_store_unlink ( s - > fd_store ) ;
assert ( s - > n_fd_store = = 0 ) ;
}
2010-01-26 21:39:06 +01:00
static void service_done ( Unit * u ) {
Service * s = SERVICE ( u ) ;
2010-01-26 07:02:51 +01:00
assert ( s ) ;
free ( s - > pid_file ) ;
s - > pid_file = NULL ;
2010-06-16 05:10:31 +02:00
free ( s - > status_text ) ;
s - > status_text = NULL ;
2014-03-25 14:15:45 +01:00
free ( s - > reboot_arg ) ;
s - > reboot_arg = NULL ;
2013-11-27 20:23:18 +01:00
s - > exec_runtime = exec_runtime_unref ( s - > exec_runtime ) ;
2010-04-10 17:53:17 +02:00
exec_command_free_array ( s - > exec_command , _SERVICE_EXEC_COMMAND_MAX ) ;
2010-01-26 07:02:51 +01:00
s - > control_command = NULL ;
2011-01-20 18:46:38 +01:00
s - > main_command = NULL ;
2010-01-26 07:02:51 +01:00
2014-07-03 12:47:40 +02:00
exit_status_set_free ( & s - > restart_prevent_status ) ;
exit_status_set_free ( & s - > restart_force_status ) ;
exit_status_set_free ( & s - > success_status ) ;
2012-08-13 13:58:01 +02:00
2010-01-26 07:02:51 +01:00
/* This will leak a process, but at least no memory or any of
* our resources */
2010-04-11 00:22:36 +02:00
service_unwatch_main_pid ( s ) ;
service_unwatch_control_pid ( s ) ;
2012-01-19 23:58:07 +01:00
service_unwatch_pid_file ( s ) ;
2010-01-26 07:02:51 +01:00
2010-04-15 23:16:16 +02:00
if ( s - > bus_name ) {
2012-01-15 12:04:08 +01:00
unit_unwatch_bus_name ( u , s - > bus_name ) ;
2010-04-15 23:16:16 +02:00
free ( s - > bus_name ) ;
s - > bus_name = NULL ;
}
2014-08-22 19:02:03 +02:00
s - > bus_endpoint_fd = safe_close ( s - > bus_endpoint_fd ) ;
2010-04-15 06:19:54 +02:00
service_close_socket_fd ( s ) ;
2010-06-19 04:25:28 +02:00
service_connection_unref ( s ) ;
2010-04-15 06:19:54 +02:00
2012-01-06 23:08:54 +01:00
unit_ref_unset ( & s - > accept_socket ) ;
2010-10-05 19:49:15 +02:00
2012-02-08 10:10:34 +01:00
service_stop_watchdog ( s ) ;
2013-11-19 21:12:59 +01:00
s - > timer_event_source = sd_event_source_unref ( s - > timer_event_source ) ;
2015-01-06 00:26:25 +01:00
service_release_resources ( u ) ;
2013-11-19 21:12:59 +01:00
}
2015-01-07 01:18:13 +01:00
static int on_fd_store_io ( sd_event_source * e , int fd , uint32_t revents , void * userdata ) {
ServiceFDStore * fs = userdata ;
assert ( e ) ;
assert ( fs ) ;
/* If we get either EPOLLHUP or EPOLLERR, it's time to remove this entry from the fd store */
service_fd_store_unlink ( fs ) ;
return 0 ;
}
static int service_add_fd_store ( Service * s , int fd ) {
ServiceFDStore * fs ;
int r ;
assert ( s ) ;
assert ( fd > = 0 ) ;
if ( s - > n_fd_store > = s - > n_fd_store_max )
return 0 ;
LIST_FOREACH ( fd_store , fs , s - > fd_store ) {
r = same_fd ( fs - > fd , fd ) ;
if ( r < 0 )
return r ;
if ( r > 0 ) {
/* Already included */
safe_close ( fd ) ;
return 1 ;
}
}
fs = new0 ( ServiceFDStore , 1 ) ;
if ( ! fs )
return - ENOMEM ;
fs - > fd = fd ;
fs - > service = s ;
r = sd_event_add_io ( UNIT ( s ) - > manager - > event , & fs - > event_source , fd , 0 , on_fd_store_io , fs ) ;
if ( r < 0 ) {
free ( fs ) ;
return r ;
}
LIST_PREPEND ( fd_store , s - > fd_store , fs ) ;
s - > n_fd_store + + ;
return 1 ;
}
static int service_add_fd_store_set ( Service * s , FDSet * fds ) {
int r ;
assert ( s ) ;
if ( fdset_size ( fds ) < = 0 )
return 0 ;
while ( s - > n_fd_store < s - > n_fd_store_max ) {
_cleanup_close_ int fd = - 1 ;
fd = fdset_steal_first ( fds ) ;
if ( fd < 0 )
break ;
r = service_add_fd_store ( s , fd ) ;
if ( r < 0 )
return log_unit_error_errno ( UNIT ( s ) - > id , r , " %s: Couldn't add fd to fd store: %m " , UNIT ( s ) - > id ) ;
if ( r > 0 ) {
log_unit_debug ( UNIT ( s ) - > id , " %s: added fd to fd store. " , UNIT ( s ) - > id ) ;
fd = - 1 ;
}
}
if ( fdset_size ( fds ) > 0 )
log_unit_warning ( UNIT ( s ) - > id , " %s: tried to store more fds than FDStoreMax=%u allows, closing remaining. " , UNIT ( s ) - > id , s - > n_fd_store_max ) ;
return 0 ;
}
2013-11-19 21:12:59 +01:00
static int service_arm_timer ( Service * s , usec_t usec ) {
int r ;
assert ( s ) ;
if ( s - > timer_event_source ) {
r = sd_event_source_set_time ( s - > timer_event_source , now ( CLOCK_MONOTONIC ) + usec ) ;
if ( r < 0 )
return r ;
return sd_event_source_set_enabled ( s - > timer_event_source , SD_EVENT_ONESHOT ) ;
}
2014-03-24 02:49:09 +01:00
return sd_event_add_time (
UNIT ( s ) - > manager - > event ,
& s - > timer_event_source ,
CLOCK_MONOTONIC ,
now ( CLOCK_MONOTONIC ) + usec , 0 ,
service_dispatch_timer , s ) ;
2010-01-26 07:02:51 +01:00
}
2010-04-13 04:00:03 +02:00
static int service_verify ( Service * s ) {
assert ( s ) ;
2012-01-15 12:25:20 +01:00
if ( UNIT ( s ) - > load_state ! = UNIT_LOADED )
2010-04-13 04:00:03 +02:00
return 0 ;
2014-08-21 18:50:42 +02:00
if ( ! s - > exec_command [ SERVICE_EXEC_START ] & & ! s - > exec_command [ SERVICE_EXEC_STOP ] ) {
2014-11-27 20:20:23 +01:00
log_unit_error ( UNIT ( s ) - > id , " %s lacks both ExecStart= and ExecStop= setting. Refusing. " , UNIT ( s ) - > id ) ;
2010-04-13 04:00:03 +02:00
return - EINVAL ;
}
2014-08-21 18:50:42 +02:00
if ( s - > type ! = SERVICE_ONESHOT & & ! s - > exec_command [ SERVICE_EXEC_START ] ) {
2014-11-27 20:20:23 +01:00
log_unit_error ( UNIT ( s ) - > id , " %s has no ExecStart= setting, which is only allowed for Type=oneshot services. Refusing. " , UNIT ( s ) - > id ) ;
2014-08-21 18:50:42 +02:00
return - EINVAL ;
}
if ( ! s - > remain_after_exit & & ! s - > exec_command [ SERVICE_EXEC_START ] ) {
2014-11-27 20:20:23 +01:00
log_unit_error ( UNIT ( s ) - > id , " %s has no ExecStart= setting, which is only allowed for RemainAfterExit=yes services. Refusing. " , UNIT ( s ) - > id ) ;
2014-08-21 18:50:42 +02:00
return - EINVAL ;
}
if ( s - > type ! = SERVICE_ONESHOT & & s - > exec_command [ SERVICE_EXEC_START ] - > command_next ) {
2014-11-27 20:20:23 +01:00
log_unit_error ( UNIT ( s ) - > id , " %s has more than one ExecStart= setting, which is only allowed for Type=oneshot services. Refusing. " , UNIT ( s ) - > id ) ;
2010-06-19 04:25:28 +02:00
return - EINVAL ;
}
2013-08-09 12:54:10 +02:00
if ( s - > type = = SERVICE_ONESHOT & & s - > restart ! = SERVICE_RESTART_NO ) {
2014-11-27 20:20:23 +01:00
log_unit_error ( UNIT ( s ) - > id , " %s has Restart= setting other than no, which isn't allowed for Type=oneshot services. Refusing. " , UNIT ( s ) - > id ) ;
2014-07-03 12:47:40 +02:00
return - EINVAL ;
}
2014-07-03 15:50:31 +02:00
if ( s - > type = = SERVICE_ONESHOT & & ! exit_status_set_is_empty ( & s - > restart_force_status ) ) {
2014-11-27 20:20:23 +01:00
log_unit_error ( UNIT ( s ) - > id , " %s has RestartForceStatus= set, which isn't allowed for Type=oneshot services. Refusing. " , UNIT ( s ) - > id ) ;
2013-08-09 12:54:10 +02:00
return - EINVAL ;
}
2010-04-15 23:16:16 +02:00
if ( s - > type = = SERVICE_DBUS & & ! s - > bus_name ) {
2014-11-27 20:20:23 +01:00
log_unit_error ( UNIT ( s ) - > id , " %s is of type D-Bus but no D-Bus service name has been specified. Refusing. " , UNIT ( s ) - > id ) ;
2010-06-19 16:57:54 +02:00
return - EINVAL ;
}
2012-05-03 14:42:49 +02:00
if ( s - > bus_name & & s - > type ! = SERVICE_DBUS )
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s has a D-Bus service name specified, but is not of type dbus. Ignoring. " , UNIT ( s ) - > id ) ;
2012-05-03 14:42:49 +02:00
2014-01-29 13:49:54 +01:00
if ( s - > exec_context . pam_name & & ! ( s - > kill_context . kill_mode = = KILL_CONTROL_GROUP | | s - > kill_context . kill_mode = = KILL_MIXED ) ) {
2014-11-27 20:20:23 +01:00
log_unit_error ( UNIT ( s ) - > id , " %s has PAM enabled. Kill mode must be set to 'control-group' or 'mixed'. Refusing. " , UNIT ( s ) - > id ) ;
2010-04-15 23:16:16 +02:00
return - EINVAL ;
}
2010-04-13 04:00:03 +02:00
return 0 ;
}
2010-07-03 19:48:33 +02:00
static int service_add_default_dependencies ( Service * s ) {
int r ;
assert ( s ) ;
/* Add a number of automatic dependencies useful for the
* majority of services . */
/* First, pull in base system */
2014-08-21 16:19:25 +02:00
r = unit_add_two_dependencies_by_name ( UNIT ( s ) , UNIT_AFTER , UNIT_REQUIRES , SPECIAL_BASIC_TARGET , NULL , true ) ;
2014-01-06 04:52:17 +01:00
if ( r < 0 )
return r ;
2010-07-03 19:48:33 +02:00
/* Second, activate normal shutdown */
2015-01-07 22:08:25 +01:00
return unit_add_two_dependencies_by_name ( UNIT ( s ) , UNIT_BEFORE , UNIT_CONFLICTS , SPECIAL_SHUTDOWN_TARGET , NULL , true ) ;
2010-07-03 19:48:33 +02:00
}
2011-09-22 03:29:51 +02:00
static void service_fix_output ( Service * s ) {
assert ( s ) ;
/* If nothing has been explicitly configured, patch default
* output in . If input is socket / tty we avoid this however ,
* since in that case we want output to default to the same
* place as we read input from . */
if ( s - > exec_context . std_error = = EXEC_OUTPUT_INHERIT & &
s - > exec_context . std_output = = EXEC_OUTPUT_INHERIT & &
s - > exec_context . std_input = = EXEC_INPUT_NULL )
2012-01-15 12:25:20 +01:00
s - > exec_context . std_error = UNIT ( s ) - > manager - > default_std_error ;
2011-09-22 03:29:51 +02:00
if ( s - > exec_context . std_output = = EXEC_OUTPUT_INHERIT & &
s - > exec_context . std_input = = EXEC_INPUT_NULL )
2012-01-15 12:25:20 +01:00
s - > exec_context . std_output = UNIT ( s ) - > manager - > default_std_output ;
2011-09-22 03:29:51 +02:00
}
2015-01-07 22:08:25 +01:00
static int service_add_extras ( Service * s ) {
int r ;
assert ( s ) ;
if ( s - > type = = _SERVICE_TYPE_INVALID ) {
/* Figure out a type automatically */
if ( s - > bus_name )
s - > type = SERVICE_DBUS ;
else if ( s - > exec_command [ SERVICE_EXEC_START ] )
s - > type = SERVICE_SIMPLE ;
else
s - > type = SERVICE_ONESHOT ;
}
/* Oneshot services have disabled start timeout by default */
if ( s - > type = = SERVICE_ONESHOT & & ! s - > start_timeout_defined )
s - > timeout_start_usec = 0 ;
service_fix_output ( s ) ;
r = unit_patch_contexts ( UNIT ( s ) ) ;
if ( r < 0 )
return r ;
r = unit_add_exec_dependencies ( UNIT ( s ) , & s - > exec_context ) ;
if ( r < 0 )
return r ;
r = unit_add_default_slice ( UNIT ( s ) , & s - > cgroup_context ) ;
if ( r < 0 )
return r ;
if ( s - > type = = SERVICE_NOTIFY & & s - > notify_access = = NOTIFY_NONE )
s - > notify_access = NOTIFY_MAIN ;
if ( s - > watchdog_usec > 0 & & s - > notify_access = = NOTIFY_NONE )
s - > notify_access = NOTIFY_MAIN ;
if ( s - > bus_name ) {
const char * n ;
r = unit_watch_bus_name ( UNIT ( s ) , s - > bus_name ) ;
if ( r < 0 )
return r ;
2015-02-03 02:05:59 +01:00
n = strjoina ( s - > bus_name , " .busname " ) ;
2015-01-07 22:08:25 +01:00
r = unit_add_dependency_by_name ( UNIT ( s ) , UNIT_AFTER , n , NULL , true ) ;
if ( r < 0 )
return r ;
}
if ( UNIT ( s ) - > default_dependencies ) {
r = service_add_default_dependencies ( s ) ;
if ( r < 0 )
return r ;
}
return 0 ;
}
2010-04-10 17:53:17 +02:00
static int service_load ( Unit * u ) {
Service * s = SERVICE ( u ) ;
2014-08-21 16:19:25 +02:00
int r ;
2010-04-10 17:53:17 +02:00
assert ( s ) ;
2010-01-29 04:42:57 +01:00
2010-01-23 01:52:57 +01:00
/* Load a .service file */
2013-06-28 04:12:58 +02:00
r = unit_load_fragment ( u ) ;
if ( r < 0 )
2010-01-23 01:52:57 +01:00
return r ;
2010-04-06 02:43:58 +02:00
/* Still nothing found? Then let's give up */
2012-01-15 12:04:08 +01:00
if ( u - > load_state = = UNIT_STUB )
2010-04-06 02:43:58 +02:00
return - ENOENT ;
2010-01-26 04:18:44 +01:00
2010-04-06 02:43:58 +02:00
/* This is a new unit? Then let's add in some extras */
2012-01-15 12:04:08 +01:00
if ( u - > load_state = = UNIT_LOADED ) {
2013-06-28 04:12:58 +02:00
/* We were able to load something, then let's add in
* the dropin directories . */
r = unit_load_dropin ( u ) ;
if ( r < 0 )
return r ;
2015-01-07 22:08:25 +01:00
/* This is a new unit? Then let's add in some
* extras */
r = service_add_extras ( s ) ;
2014-03-19 20:40:05 +01:00
if ( r < 0 )
return r ;
2010-03-31 16:29:55 +02:00
}
2010-04-13 04:00:03 +02:00
return service_verify ( s ) ;
2010-01-26 04:18:44 +01:00
}
2010-01-26 21:39:06 +01:00
static void service_dump ( Unit * u , FILE * f , const char * prefix ) {
2010-01-23 01:52:57 +01:00
ServiceExecCommand c ;
2010-01-26 21:39:06 +01:00
Service * s = SERVICE ( u ) ;
2010-02-03 14:21:48 +01:00
const char * prefix2 ;
2010-01-23 01:52:57 +01:00
assert ( s ) ;
2014-08-21 16:15:49 +02:00
prefix = strempty ( prefix ) ;
2015-02-03 02:05:59 +01:00
prefix2 = strjoina ( prefix , " \t " ) ;
2010-01-26 07:02:51 +01:00
2010-01-23 01:52:57 +01:00
fprintf ( f ,
2010-02-14 22:43:08 +01:00
" %sService State: %s \n "
2012-02-03 02:01:35 +01:00
" %sResult: %s \n "
" %sReload Result: %s \n "
2010-02-14 22:43:08 +01:00
" %sPermissionsStartOnly: %s \n "
2010-03-31 16:29:55 +02:00
" %sRootDirectoryStartOnly: %s \n "
2010-08-17 19:37:36 +02:00
" %sRemainAfterExit: %s \n "
2011-02-13 18:51:30 +01:00
" %sGuessMainPID: %s \n "
2010-06-18 23:12:48 +02:00
" %sType: %s \n "
2010-08-09 17:03:46 +02:00
" %sRestart: %s \n "
2014-08-21 17:03:15 +02:00
" %sNotifyAccess: %s \n "
" %sNotifyState: %s \n " ,
2010-02-14 22:43:08 +01:00
prefix , service_state_to_string ( s - > state ) ,
2012-02-03 02:01:35 +01:00
prefix , service_result_to_string ( s - > result ) ,
prefix , service_result_to_string ( s - > reload_result ) ,
2010-02-14 22:43:08 +01:00
prefix , yes_no ( s - > permissions_start_only ) ,
2010-03-31 16:29:55 +02:00
prefix , yes_no ( s - > root_directory_start_only ) ,
2010-08-17 19:37:36 +02:00
prefix , yes_no ( s - > remain_after_exit ) ,
2011-02-13 18:51:30 +01:00
prefix , yes_no ( s - > guess_main_pid ) ,
2010-06-18 23:12:48 +02:00
prefix , service_type_to_string ( s - > type ) ,
2010-08-09 17:03:46 +02:00
prefix , service_restart_to_string ( s - > restart ) ,
2014-08-21 17:03:15 +02:00
prefix , notify_access_to_string ( s - > notify_access ) ,
prefix , notify_state_to_string ( s - > notify_state ) ) ;
2010-01-23 01:52:57 +01:00
2010-04-08 03:48:27 +02:00
if ( s - > control_pid > 0 )
fprintf ( f ,
2013-12-30 23:22:26 +01:00
" %sControl PID: " PID_FMT " \n " ,
prefix , s - > control_pid ) ;
2010-04-08 03:48:27 +02:00
if ( s - > main_pid > 0 )
fprintf ( f ,
2013-12-30 23:22:26 +01:00
" %sMain PID: " PID_FMT " \n "
2011-04-28 04:56:53 +02:00
" %sMain PID Known: %s \n "
" %sMain PID Alien: %s \n " ,
2013-12-30 23:22:26 +01:00
prefix , s - > main_pid ,
2011-04-28 04:56:53 +02:00
prefix , yes_no ( s - > main_pid_known ) ,
prefix , yes_no ( s - > main_pid_alien ) ) ;
2010-04-08 03:48:27 +02:00
2010-01-26 04:18:44 +01:00
if ( s - > pid_file )
fprintf ( f ,
" %sPIDFile: %s \n " ,
prefix , s - > pid_file ) ;
2010-04-15 23:16:16 +02:00
if ( s - > bus_name )
fprintf ( f ,
" %sBusName: %s \n "
" %sBus Name Good: %s \n " ,
prefix , s - > bus_name ,
prefix , yes_no ( s - > bus_name_good ) ) ;
2012-07-19 23:47:10 +02:00
kill_context_dump ( & s - > kill_context , f , prefix ) ;
2010-01-23 01:52:57 +01:00
exec_context_dump ( & s - > exec_context , f , prefix ) ;
2010-04-10 17:53:17 +02:00
for ( c = 0 ; c < _SERVICE_EXEC_COMMAND_MAX ; c + + ) {
2010-01-23 01:52:57 +01:00
2010-01-26 07:02:51 +01:00
if ( ! s - > exec_command [ c ] )
continue ;
2010-04-23 20:25:55 +02:00
fprintf ( f , " %s-> %s: \n " ,
2010-01-30 01:55:42 +01:00
prefix , service_exec_command_to_string ( c ) ) ;
2010-01-26 07:02:51 +01:00
exec_command_dump_list ( s - > exec_command [ c ] , f , prefix2 ) ;
2010-01-23 01:52:57 +01:00
}
2010-01-26 07:02:51 +01:00
2010-06-16 05:10:31 +02:00
if ( s - > status_text )
fprintf ( f , " %sStatus Text: %s \n " ,
prefix , s - > status_text ) ;
2015-01-06 00:26:25 +01:00
if ( s - > n_fd_store_max > 0 ) {
fprintf ( f ,
" %sFile Descriptor Store Max: %u \n "
" %sFile Descriptor Store Current: %u \n " ,
prefix , s - > n_fd_store_max ,
prefix , s - > n_fd_store ) ;
}
2010-01-23 01:52:57 +01:00
}
2011-11-10 09:55:47 +01:00
static int service_load_pid_file ( Service * s , bool may_warn ) {
2013-04-18 09:11:22 +02:00
_cleanup_free_ char * k = NULL ;
2010-01-26 04:18:44 +01:00
int r ;
2010-06-17 22:55:53 +02:00
pid_t pid ;
2010-01-26 04:18:44 +01:00
assert ( s ) ;
if ( ! s - > pid_file )
2011-09-21 02:25:17 +02:00
return - ENOENT ;
2010-01-26 04:18:44 +01:00
2013-03-02 14:28:58 +01:00
r = read_one_line_file ( s - > pid_file , & k ) ;
if ( r < 0 ) {
2011-11-10 09:55:47 +01:00
if ( may_warn )
2014-11-27 20:20:23 +01:00
log_unit_info ( UNIT ( s ) - > id , " PID file %s not readable (yet?) after %s. " , s - > pid_file , service_state_to_string ( s - > state ) ) ;
2010-01-26 04:18:44 +01:00
return r ;
2011-09-22 13:10:32 +02:00
}
2010-01-26 04:18:44 +01:00
2010-06-17 22:55:53 +02:00
r = parse_pid ( k , & pid ) ;
2013-03-03 07:32:34 +01:00
if ( r < 0 ) {
if ( may_warn )
2014-11-28 13:17:02 +01:00
log_unit_info_errno ( UNIT ( s ) - > id , r , " Failed to read PID from file %s: %m " , s - > pid_file ) ;
2010-06-17 22:55:53 +02:00
return r ;
2013-03-03 07:32:34 +01:00
}
2010-06-15 19:47:13 +02:00
2014-02-17 18:28:53 +01:00
if ( ! pid_is_alive ( pid ) ) {
2011-11-10 09:55:47 +01:00
if ( may_warn )
2014-11-27 20:20:23 +01:00
log_unit_info ( UNIT ( s ) - > id , " PID " PID_FMT " read from file %s does not exist or is a zombie. " , pid , s - > pid_file ) ;
2014-02-14 19:38:50 +01:00
return - ESRCH ;
}
2011-09-20 21:43:30 +02:00
if ( s - > main_pid_known ) {
if ( pid = = s - > main_pid )
return 0 ;
2014-11-27 20:20:23 +01:00
log_unit_debug ( UNIT ( s ) - > id , " Main PID changing: " PID_FMT " -> " PID_FMT , s - > main_pid , pid ) ;
2014-08-21 16:19:25 +02:00
2011-09-20 21:43:30 +02:00
service_unwatch_main_pid ( s ) ;
s - > main_pid_known = false ;
2011-12-03 02:13:30 +01:00
} else
2014-11-27 20:20:23 +01:00
log_unit_debug ( UNIT ( s ) - > id , " Main PID loaded: " PID_FMT , pid ) ;
2011-09-20 21:43:30 +02:00
2013-03-02 14:28:58 +01:00
r = service_set_main_pid ( s , pid ) ;
if ( r < 0 )
2010-04-08 04:05:56 +02:00
return r ;
2013-03-02 14:28:58 +01:00
r = unit_watch_pid ( UNIT ( s ) , pid ) ;
2013-03-03 07:32:34 +01:00
if ( r < 0 ) {
2010-06-17 22:55:53 +02:00
/* FIXME: we need to do something here */
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " Failed to watch PID " PID_FMT " from service %s " , pid , UNIT ( s ) - > id ) ;
2010-06-17 22:55:53 +02:00
return r ;
2013-03-03 07:32:34 +01:00
}
2010-01-26 04:18:44 +01:00
return 0 ;
}
2010-10-27 03:16:49 +02:00
static int service_search_main_pid ( Service * s ) {
pid_t pid ;
int r ;
assert ( s ) ;
2011-02-13 18:51:30 +01:00
/* If we know it anyway, don't ever fallback to unreliable
* heuristics */
2010-10-27 03:16:49 +02:00
if ( s - > main_pid_known )
return 0 ;
2011-02-13 18:51:30 +01:00
if ( ! s - > guess_main_pid )
return 0 ;
2010-10-27 03:16:49 +02:00
assert ( s - > main_pid < = 0 ) ;
2013-06-27 04:14:27 +02:00
pid = unit_search_main_pid ( UNIT ( s ) ) ;
2013-03-02 14:28:58 +01:00
if ( pid < = 0 )
2010-10-27 03:16:49 +02:00
return - ENOENT ;
2014-11-27 20:20:23 +01:00
log_unit_debug ( UNIT ( s ) - > id , " Main PID guessed: " PID_FMT , pid ) ;
2013-03-02 14:28:58 +01:00
r = service_set_main_pid ( s , pid ) ;
if ( r < 0 )
2010-10-27 03:16:49 +02:00
return r ;
2013-03-02 14:28:58 +01:00
r = unit_watch_pid ( UNIT ( s ) , pid ) ;
2014-08-21 16:19:25 +02:00
if ( r < 0 ) {
2010-10-27 03:16:49 +02:00
/* FIXME: we need to do something here */
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " Failed to watch PID " PID_FMT " from service %s " , pid , UNIT ( s ) - > id ) ;
2014-08-21 16:19:25 +02:00
return r ;
}
return 0 ;
2010-10-27 03:16:49 +02:00
}
2010-01-26 04:18:44 +01:00
static void service_set_state ( Service * s , ServiceState state ) {
ServiceState old_state ;
2012-05-24 02:22:35 +02:00
const UnitActiveState * table ;
2013-12-11 20:49:43 +01:00
2010-01-23 01:52:57 +01:00
assert ( s ) ;
2012-05-24 02:22:35 +02:00
table = s - > type = = SERVICE_IDLE ? state_translation_table_idle : state_translation_table ;
2010-01-26 04:18:44 +01:00
old_state = s - > state ;
2010-01-23 01:52:57 +01:00
s - > state = state ;
2010-01-26 04:18:44 +01:00
2011-12-03 02:13:30 +01:00
service_unwatch_pid_file ( s ) ;
2013-12-11 20:49:43 +01:00
if ( ! IN_SET ( state ,
SERVICE_START_PRE , SERVICE_START , SERVICE_START_POST ,
SERVICE_RELOAD ,
2013-12-18 04:19:20 +01:00
SERVICE_STOP , SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL ,
2014-10-28 16:35:40 +01:00
SERVICE_STOP_SIGABRT , SERVICE_STOP_POST ,
2013-12-11 20:49:43 +01:00
SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL ,
SERVICE_AUTO_RESTART ) )
2013-11-19 21:12:59 +01:00
s - > timer_event_source = sd_event_source_unref ( s - > timer_event_source ) ;
2010-01-26 04:18:44 +01:00
2013-12-11 20:49:43 +01:00
if ( ! IN_SET ( state ,
SERVICE_START , SERVICE_START_POST ,
SERVICE_RUNNING , SERVICE_RELOAD ,
2013-12-18 04:19:20 +01:00
SERVICE_STOP , SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL ,
2014-10-28 16:35:40 +01:00
SERVICE_STOP_SIGABRT , SERVICE_STOP_POST ,
2013-12-18 04:19:20 +01:00
SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL ) ) {
2010-04-11 00:22:36 +02:00
service_unwatch_main_pid ( s ) ;
2011-01-20 18:46:38 +01:00
s - > main_command = NULL ;
}
2010-01-26 04:18:44 +01:00
2013-12-11 20:49:43 +01:00
if ( ! IN_SET ( state ,
SERVICE_START_PRE , SERVICE_START , SERVICE_START_POST ,
SERVICE_RELOAD ,
2013-12-18 04:19:20 +01:00
SERVICE_STOP , SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL ,
2014-10-28 16:35:40 +01:00
SERVICE_STOP_SIGABRT , SERVICE_STOP_POST ,
2013-12-11 20:49:43 +01:00
SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL ) ) {
2010-04-11 00:22:36 +02:00
service_unwatch_control_pid ( s ) ;
2010-01-26 04:18:44 +01:00
s - > control_command = NULL ;
2010-04-21 03:27:44 +02:00
s - > control_command_id = _SERVICE_EXEC_COMMAND_INVALID ;
2010-04-10 17:53:17 +02:00
}
2010-01-26 04:18:44 +01:00
2014-02-06 17:17:51 +01:00
if ( IN_SET ( state , SERVICE_DEAD , SERVICE_FAILED , SERVICE_AUTO_RESTART ) )
unit_unwatch_all_pids ( UNIT ( s ) ) ;
2013-12-11 20:49:43 +01:00
if ( ! IN_SET ( state ,
SERVICE_START_PRE , SERVICE_START , SERVICE_START_POST ,
SERVICE_RUNNING , SERVICE_RELOAD ,
SERVICE_STOP , SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL , SERVICE_STOP_POST ,
2014-10-28 16:35:40 +01:00
SERVICE_STOP_SIGABRT , SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL ) & &
2012-01-15 12:25:20 +01:00
! ( state = = SERVICE_DEAD & & UNIT ( s ) - > job ) ) {
2010-04-15 06:19:54 +02:00
service_close_socket_fd ( s ) ;
2010-06-19 04:25:28 +02:00
service_connection_unref ( s ) ;
}
2010-04-15 06:19:54 +02:00
2013-12-12 03:03:03 +01:00
if ( ! IN_SET ( state , SERVICE_START_POST , SERVICE_RUNNING , SERVICE_RELOAD ) )
2012-02-01 17:17:12 +01:00
service_stop_watchdog ( s ) ;
2010-07-12 02:31:40 +02:00
/* For the inactive states unit_notify() will trim the cgroup,
* but for exit we have to do that ourselves . . . */
2012-01-15 12:25:20 +01:00
if ( state = = SERVICE_EXITED & & UNIT ( s ) - > manager - > n_reloading < = 0 )
2014-12-09 02:31:42 +01:00
unit_destroy_cgroup_if_empty ( UNIT ( s ) ) ;
2010-07-12 02:31:40 +02:00
2013-11-14 15:52:54 +01:00
/* For remain_after_exit services, let's see if we can "release" the
* hold on the console , since unit_notify ( ) only does that in case of
* change of state */
2014-08-21 16:20:17 +02:00
if ( state = = SERVICE_EXITED & &
s - > remain_after_exit & &
2013-11-14 15:52:54 +01:00
UNIT ( s ) - > manager - > n_on_console > 0 ) {
2014-08-21 16:20:17 +02:00
ExecContext * ec ;
ec = unit_get_exec_context ( UNIT ( s ) ) ;
2013-11-14 15:52:54 +01:00
if ( ec & & exec_context_may_touch_console ( ec ) ) {
Manager * m = UNIT ( s ) - > manager ;
m - > n_on_console - - ;
if ( m - > n_on_console = = 0 )
/* unset no_console_output flag, since the console is free */
m - > no_console_output = false ;
}
}
2010-04-10 17:53:17 +02:00
if ( old_state ! = state )
2014-11-27 20:20:23 +01:00
log_unit_debug ( UNIT ( s ) - > id , " %s changed %s -> %s " , UNIT ( s ) - > id , service_state_to_string ( old_state ) , service_state_to_string ( state ) ) ;
2010-01-27 04:31:52 +01:00
2012-05-24 02:22:35 +02:00
unit_notify ( UNIT ( s ) , table [ old_state ] , table [ state ] , s - > reload_result = = SERVICE_SUCCESS ) ;
2012-02-03 02:01:35 +01:00
s - > reload_result = SERVICE_SUCCESS ;
2010-01-26 04:18:44 +01:00
}
2010-04-21 03:27:44 +02:00
static int service_coldplug ( Unit * u ) {
Service * s = SERVICE ( u ) ;
int r ;
assert ( s ) ;
assert ( s - > state = = SERVICE_DEAD ) ;
if ( s - > deserialized_state ! = s - > state ) {
2013-12-18 04:19:20 +01:00
if ( IN_SET ( s - > deserialized_state ,
SERVICE_START_PRE , SERVICE_START , SERVICE_START_POST ,
SERVICE_RELOAD ,
SERVICE_STOP , SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL ,
2014-10-28 16:35:40 +01:00
SERVICE_STOP_SIGABRT , SERVICE_STOP_POST ,
2013-12-18 04:19:20 +01:00
SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL ) ) {
2013-11-22 19:17:52 +01:00
usec_t k ;
2013-07-01 00:03:57 +02:00
2013-12-18 04:19:20 +01:00
k = IN_SET ( s - > deserialized_state , SERVICE_START_PRE , SERVICE_START , SERVICE_START_POST , SERVICE_RELOAD ) ? s - > timeout_start_usec : s - > timeout_stop_usec ;
2010-04-23 20:28:33 +02:00
2013-11-22 19:17:52 +01:00
/* For the start/stop timeouts 0 means off */
if ( k > 0 ) {
r = service_arm_timer ( s , k ) ;
2012-11-23 21:37:58 +01:00
if ( r < 0 )
2010-04-23 20:28:33 +02:00
return r ;
}
}
2010-04-21 03:27:44 +02:00
2013-11-22 19:17:52 +01:00
if ( s - > deserialized_state = = SERVICE_AUTO_RESTART ) {
/* The restart timeouts 0 means immediately */
r = service_arm_timer ( s , s - > restart_usec ) ;
if ( r < 0 )
return r ;
}
2014-02-17 18:28:53 +01:00
if ( pid_is_unwaited ( s - > main_pid ) & &
2013-12-18 04:19:20 +01:00
( ( s - > deserialized_state = = SERVICE_START & & IN_SET ( s - > type , SERVICE_FORKING , SERVICE_DBUS , SERVICE_ONESHOT , SERVICE_NOTIFY ) ) | |
IN_SET ( s - > deserialized_state ,
SERVICE_START , SERVICE_START_POST ,
SERVICE_RUNNING , SERVICE_RELOAD ,
SERVICE_STOP , SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL ,
2014-10-28 16:35:40 +01:00
SERVICE_STOP_SIGABRT , SERVICE_STOP_POST ,
2013-12-18 04:19:20 +01:00
SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL ) ) ) {
r = unit_watch_pid ( UNIT ( s ) , s - > main_pid ) ;
if ( r < 0 )
return r ;
}
2010-04-21 03:27:44 +02:00
2014-02-17 18:28:53 +01:00
if ( pid_is_unwaited ( s - > control_pid ) & &
2013-12-18 04:19:20 +01:00
IN_SET ( s - > deserialized_state ,
SERVICE_START_PRE , SERVICE_START , SERVICE_START_POST ,
SERVICE_RELOAD ,
SERVICE_STOP , SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL ,
2014-10-28 16:35:40 +01:00
SERVICE_STOP_SIGABRT , SERVICE_STOP_POST ,
2013-12-18 04:19:20 +01:00
SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL ) ) {
r = unit_watch_pid ( UNIT ( s ) , s - > control_pid ) ;
if ( r < 0 )
return r ;
}
2010-04-21 03:27:44 +02:00
2014-02-06 17:17:51 +01:00
if ( ! IN_SET ( s - > deserialized_state , SERVICE_DEAD , SERVICE_FAILED , SERVICE_AUTO_RESTART ) )
unit_watch_all_pids ( UNIT ( s ) ) ;
2013-12-11 20:49:43 +01:00
if ( IN_SET ( s - > deserialized_state , SERVICE_START_POST , SERVICE_RUNNING , SERVICE_RELOAD ) )
service_start_watchdog ( s ) ;
2012-02-08 10:10:34 +01:00
2010-04-21 03:27:44 +02:00
service_set_state ( s , s - > deserialized_state ) ;
}
2013-11-22 19:17:52 +01:00
2010-04-21 03:27:44 +02:00
return 0 ;
}
2010-01-26 07:02:51 +01:00
static int service_collect_fds ( Service * s , int * * fds , unsigned * n_fds ) {
2015-01-06 00:26:25 +01:00
_cleanup_free_ int * rfds = NULL ;
unsigned rn_fds = 0 ;
2010-01-26 07:02:51 +01:00
Iterator i ;
int r ;
2012-01-06 23:08:54 +01:00
Unit * u ;
2010-01-26 07:02:51 +01:00
assert ( s ) ;
assert ( fds ) ;
assert ( n_fds ) ;
2010-06-19 04:25:28 +02:00
if ( s - > socket_fd > = 0 )
return 0 ;
2012-01-15 12:25:20 +01:00
SET_FOREACH ( u , UNIT ( s ) - > dependencies [ UNIT_TRIGGERED_BY ] , i ) {
2010-01-26 07:02:51 +01:00
int * cfds ;
unsigned cn_fds ;
2012-01-06 23:08:54 +01:00
Socket * sock ;
2012-01-15 12:04:08 +01:00
if ( u - > type ! = UNIT_SOCKET )
2012-01-06 23:08:54 +01:00
continue ;
sock = SOCKET ( u ) ;
2010-01-26 07:02:51 +01:00
2013-03-02 14:28:58 +01:00
r = socket_collect_fds ( sock , & cfds , & cn_fds ) ;
if ( r < 0 )
2015-01-06 00:26:25 +01:00
return r ;
2010-01-26 07:02:51 +01:00
2015-01-06 00:26:25 +01:00
if ( cn_fds < = 0 ) {
free ( cfds ) ;
2010-01-26 07:02:51 +01:00
continue ;
2015-01-06 00:26:25 +01:00
}
2010-01-26 07:02:51 +01:00
if ( ! rfds ) {
rfds = cfds ;
rn_fds = cn_fds ;
} else {
int * t ;
2015-01-06 00:26:25 +01:00
t = realloc ( rfds , ( rn_fds + cn_fds ) * sizeof ( int ) ) ;
2013-03-02 14:28:58 +01:00
if ( ! t ) {
2010-01-26 07:02:51 +01:00
free ( cfds ) ;
2015-01-06 00:26:25 +01:00
return - ENOMEM ;
2010-01-26 07:02:51 +01:00
}
2015-01-06 00:26:25 +01:00
memcpy ( t + rn_fds , cfds , cn_fds * sizeof ( int ) ) ;
rfds = t ;
rn_fds + = cn_fds ;
2010-01-26 07:02:51 +01:00
free ( cfds ) ;
}
}
2015-01-06 00:26:25 +01:00
if ( s - > n_fd_store > 0 ) {
ServiceFDStore * fs ;
int * t ;
t = realloc ( rfds , ( rn_fds + s - > n_fd_store ) * sizeof ( int ) ) ;
if ( ! t )
return - ENOMEM ;
rfds = t ;
LIST_FOREACH ( fd_store , fs , s - > fd_store )
rfds [ rn_fds + + ] = fs - > fd ;
}
2010-01-26 07:02:51 +01:00
* fds = rfds ;
* n_fds = rn_fds ;
2010-01-27 22:41:57 +01:00
2015-01-06 00:26:25 +01:00
rfds = NULL ;
2010-01-26 07:02:51 +01:00
return 0 ;
}
2010-02-14 22:43:08 +01:00
static int service_spawn (
Service * s ,
ExecCommand * c ,
2014-08-21 18:01:22 +02:00
usec_t timeout ,
2010-02-14 22:43:08 +01:00
bool pass_fds ,
bool apply_permissions ,
bool apply_chroot ,
2010-07-08 04:09:17 +02:00
bool apply_tty_stdin ,
2012-04-13 23:24:47 +02:00
bool is_control ,
2010-02-14 22:43:08 +01:00
pid_t * _pid ) {
2010-01-26 04:18:44 +01:00
pid_t pid ;
int r ;
2013-03-02 14:28:58 +01:00
int * fds = NULL ;
2013-04-18 09:11:22 +02:00
_cleanup_free_ int * fdsbuf = NULL ;
2010-07-08 00:47:35 +02:00
unsigned n_fds = 0 , n_env = 0 ;
2014-08-22 19:02:03 +02:00
_cleanup_free_ char * bus_endpoint_path = NULL ;
2013-04-18 09:11:22 +02:00
_cleanup_strv_free_ char
2013-03-02 14:28:58 +01:00
* * argv = NULL , * * final_env = NULL , * * our_env = NULL ;
2013-06-27 04:14:27 +02:00
const char * path ;
2014-08-23 15:28:37 +02:00
ExecParameters exec_params = {
. apply_permissions = apply_permissions ,
. apply_chroot = apply_chroot ,
. apply_tty_stdin = apply_tty_stdin ,
2014-08-22 19:02:03 +02:00
. bus_endpoint_fd = - 1 ,
2014-07-24 10:40:28 +02:00
. selinux_context_net = s - > socket_fd_selinux_context_net
2014-08-23 15:28:37 +02:00
} ;
2010-01-26 04:18:44 +01:00
assert ( s ) ;
assert ( c ) ;
assert ( _pid ) ;
2015-03-01 16:24:19 +01:00
( void ) unit_realize_cgroup ( UNIT ( s ) ) ;
if ( s - > reset_cpu_usage ) {
( void ) unit_reset_cpu_usage ( UNIT ( s ) ) ;
s - > reset_cpu_usage = false ;
}
2013-06-27 04:14:27 +02:00
2013-11-27 20:23:18 +01:00
r = unit_setup_exec_runtime ( UNIT ( s ) ) ;
if ( r < 0 )
goto fail ;
2010-06-19 04:25:28 +02:00
if ( pass_fds | |
s - > exec_context . std_input = = EXEC_INPUT_SOCKET | |
s - > exec_context . std_output = = EXEC_OUTPUT_SOCKET | |
s - > exec_context . std_error = = EXEC_OUTPUT_SOCKET ) {
2010-04-15 06:19:54 +02:00
if ( s - > socket_fd > = 0 ) {
fds = & s - > socket_fd ;
n_fds = 1 ;
2010-06-19 04:25:28 +02:00
} else {
2013-03-02 14:28:58 +01:00
r = service_collect_fds ( s , & fdsbuf , & n_fds ) ;
if ( r < 0 )
2010-06-19 04:25:28 +02:00
goto fail ;
fds = fdsbuf ;
}
2010-04-15 06:19:54 +02:00
}
2010-01-26 07:02:51 +01:00
2014-08-21 18:01:22 +02:00
if ( timeout > 0 ) {
r = service_arm_timer ( s , timeout ) ;
2013-11-22 19:17:52 +01:00
if ( r < 0 )
goto fail ;
} else
s - > timer_event_source = sd_event_source_unref ( s - > timer_event_source ) ;
2010-01-26 04:18:44 +01:00
2013-09-17 17:03:46 +02:00
r = unit_full_printf_strv ( UNIT ( s ) , c - > argv , & argv ) ;
if ( r < 0 )
2010-04-15 03:11:11 +02:00
goto fail ;
2013-12-22 22:14:05 +01:00
our_env = new0 ( char * , 4 ) ;
2012-10-18 01:18:50 +02:00
if ( ! our_env ) {
2010-07-08 00:47:35 +02:00
r = - ENOMEM ;
goto fail ;
}
2010-06-18 23:12:48 +02:00
2014-10-12 01:36:06 +02:00
if ( is_control ? s - > notify_access = = NOTIFY_ALL : s - > notify_access ! = NOTIFY_NONE )
2012-01-15 12:25:20 +01:00
if ( asprintf ( our_env + n_env + + , " NOTIFY_SOCKET=%s " , UNIT ( s ) - > manager - > notify_socket ) < 0 ) {
2010-06-18 23:12:48 +02:00
r = - ENOMEM ;
goto fail ;
}
2010-07-08 00:47:35 +02:00
if ( s - > main_pid > 0 )
2013-12-30 23:22:26 +01:00
if ( asprintf ( our_env + n_env + + , " MAINPID= " PID_FMT , s - > main_pid ) < 0 ) {
2010-06-18 23:12:48 +02:00
r = - ENOMEM ;
goto fail ;
}
2010-07-08 00:47:35 +02:00
2013-06-27 04:14:27 +02:00
if ( UNIT ( s ) - > manager - > running_as ! = SYSTEMD_SYSTEM )
2013-12-30 23:22:26 +01:00
if ( asprintf ( our_env + n_env + + , " MANAGERPID= " PID_FMT , getpid ( ) ) < 0 ) {
2012-10-18 01:18:50 +02:00
r = - ENOMEM ;
goto fail ;
}
final_env = strv_env_merge ( 2 , UNIT ( s ) - > manager - > environment , our_env , NULL ) ;
if ( ! final_env ) {
2010-07-08 00:47:35 +02:00
r = - ENOMEM ;
goto fail ;
}
2010-06-18 23:12:48 +02:00
2013-06-27 04:14:27 +02:00
if ( is_control & & UNIT ( s ) - > cgroup_path ) {
2015-02-03 02:05:59 +01:00
path = strjoina ( UNIT ( s ) - > cgroup_path , " /control " ) ;
2013-06-27 04:14:27 +02:00
cg_create ( SYSTEMD_CGROUP_CONTROLLER , path ) ;
} else
path = UNIT ( s ) - > cgroup_path ;
2014-08-22 19:02:03 +02:00
# ifdef ENABLE_KDBUS
if ( s - > exec_context . bus_endpoint ) {
r = bus_kernel_create_endpoint ( UNIT ( s ) - > manager - > running_as = = SYSTEMD_SYSTEM ? " system " : " user " ,
UNIT ( s ) - > id , & bus_endpoint_path ) ;
if ( r < 0 )
goto fail ;
/* Pass the fd to the exec_params so that the child process can upload the policy.
* Keep a reference to the fd in the service , so the endpoint is kept alive as long
* as the service is running . */
exec_params . bus_endpoint_fd = s - > bus_endpoint_fd = r ;
}
# endif
2014-08-23 15:28:37 +02:00
exec_params . argv = argv ;
exec_params . fds = fds ;
exec_params . n_fds = n_fds ;
exec_params . environment = final_env ;
exec_params . confirm_spawn = UNIT ( s ) - > manager - > confirm_spawn ;
exec_params . cgroup_supported = UNIT ( s ) - > manager - > cgroup_supported ;
exec_params . cgroup_path = path ;
2014-11-05 17:57:23 +01:00
exec_params . cgroup_delegate = s - > cgroup_context . delegate ;
2014-08-23 15:28:37 +02:00
exec_params . runtime_prefix = manager_get_runtime_prefix ( UNIT ( s ) - > manager ) ;
exec_params . unit_id = UNIT ( s ) - > id ;
exec_params . watchdog_usec = s - > watchdog_usec ;
2014-08-22 19:02:03 +02:00
exec_params . bus_endpoint_path = bus_endpoint_path ;
2014-08-23 15:28:37 +02:00
if ( s - > type = = SERVICE_IDLE )
exec_params . idle_pipe = UNIT ( s ) - > manager - > idle_pipe ;
2010-04-15 03:11:11 +02:00
r = exec_spawn ( c ,
& s - > exec_context ,
2014-08-23 15:28:37 +02:00
& exec_params ,
2013-11-27 20:23:18 +01:00
s - > exec_runtime ,
2010-04-15 03:11:11 +02:00
& pid ) ;
if ( r < 0 )
2010-01-26 04:18:44 +01:00
goto fail ;
2013-03-02 14:28:58 +01:00
r = unit_watch_pid ( UNIT ( s ) , pid ) ;
if ( r < 0 )
2010-01-26 04:18:44 +01:00
/* FIXME: we need to do something here */
goto fail ;
* _pid = pid ;
2010-01-23 01:52:57 +01:00
return 0 ;
2010-01-26 04:18:44 +01:00
fail :
if ( timeout )
2013-11-19 21:12:59 +01:00
s - > timer_event_source = sd_event_source_unref ( s - > timer_event_source ) ;
2010-01-26 04:18:44 +01:00
return r ;
}
2010-04-13 02:06:27 +02:00
static int main_pid_good ( Service * s ) {
assert ( s ) ;
/* Returns 0 if the pid is dead, 1 if it is good, -1 if we
* don ' t know */
/* If we know the pid file, then lets just check if it is
* still valid */
2011-04-28 04:56:53 +02:00
if ( s - > main_pid_known ) {
/* If it's an alien child let's check if it is still
* alive . . . */
2013-06-09 18:28:44 +02:00
if ( s - > main_pid_alien & & s - > main_pid > 0 )
2014-02-17 18:28:53 +01:00
return pid_is_alive ( s - > main_pid ) ;
2011-04-28 04:56:53 +02:00
/* .. otherwise assume we'll get a SIGCHLD for it,
* which we really should wait for to collect exit
* status and code */
2010-04-13 02:06:27 +02:00
return s - > main_pid > 0 ;
2011-04-28 04:56:53 +02:00
}
2010-04-13 02:06:27 +02:00
/* We don't know the pid */
return - EAGAIN ;
}
2013-05-03 04:51:50 +02:00
_pure_ static int control_pid_good ( Service * s ) {
2010-04-13 02:06:27 +02:00
assert ( s ) ;
return s - > control_pid > 0 ;
}
static int cgroup_good ( Service * s ) {
int r ;
assert ( s ) ;
2013-06-27 04:14:27 +02:00
if ( ! UNIT ( s ) - > cgroup_path )
return 0 ;
r = cg_is_empty_recursive ( SYSTEMD_CGROUP_CONTROLLER , UNIT ( s ) - > cgroup_path , true ) ;
2013-03-02 14:28:58 +01:00
if ( r < 0 )
2010-04-13 02:06:27 +02:00
return r ;
return ! r ;
}
2012-02-03 02:01:35 +01:00
static void service_enter_dead ( Service * s , ServiceResult f , bool allow_restart ) {
2010-01-26 04:18:44 +01:00
int r ;
assert ( s ) ;
2012-02-03 02:01:35 +01:00
if ( f ! = SERVICE_SUCCESS )
s - > result = f ;
2010-01-26 04:18:44 +01:00
2012-06-26 11:42:52 +02:00
service_set_state ( s , s - > result ! = SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD ) ;
2014-08-22 16:36:38 +02:00
if ( s - > result ! = SERVICE_SUCCESS ) {
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s failed. " , UNIT ( s ) - > id ) ;
2014-08-22 16:36:38 +02:00
failure_action ( UNIT ( s ) - > manager , s - > failure_action , s - > reboot_arg ) ;
}
2014-04-24 09:35:37 +02:00
2010-01-26 04:18:44 +01:00
if ( allow_restart & &
2010-08-09 23:33:48 +02:00
! s - > forbid_restart & &
2010-01-26 04:18:44 +01:00
( s - > restart = = SERVICE_RESTART_ALWAYS | |
2012-02-03 02:01:35 +01:00
( s - > restart = = SERVICE_RESTART_ON_SUCCESS & & s - > result = = SERVICE_SUCCESS ) | |
( s - > restart = = SERVICE_RESTART_ON_FAILURE & & s - > result ! = SERVICE_SUCCESS ) | |
2014-06-05 18:42:52 +02:00
( s - > restart = = SERVICE_RESTART_ON_ABNORMAL & & ! IN_SET ( s - > result , SERVICE_SUCCESS , SERVICE_FAILURE_EXIT_CODE ) ) | |
2013-07-25 14:07:59 +02:00
( s - > restart = = SERVICE_RESTART_ON_WATCHDOG & & s - > result = = SERVICE_FAILURE_WATCHDOG ) | |
2014-07-03 12:47:40 +02:00
( s - > restart = = SERVICE_RESTART_ON_ABORT & & IN_SET ( s - > result , SERVICE_FAILURE_SIGNAL , SERVICE_FAILURE_CORE_DUMP ) ) | |
2014-07-03 15:36:50 +02:00
( s - > main_exec_status . code = = CLD_EXITED & & set_contains ( s - > restart_force_status . status , INT_TO_PTR ( s - > main_exec_status . status ) ) ) | |
2014-07-03 12:47:40 +02:00
( IN_SET ( s - > main_exec_status . code , CLD_KILLED , CLD_DUMPED ) & & set_contains ( s - > restart_force_status . signal , INT_TO_PTR ( s - > main_exec_status . status ) ) ) ) & &
2014-07-03 15:36:50 +02:00
( s - > main_exec_status . code ! = CLD_EXITED | | ! set_contains ( s - > restart_prevent_status . status , INT_TO_PTR ( s - > main_exec_status . status ) ) ) & &
2014-07-03 12:47:40 +02:00
( ! IN_SET ( s - > main_exec_status . code , CLD_KILLED , CLD_DUMPED ) | | ! set_contains ( s - > restart_prevent_status . signal , INT_TO_PTR ( s - > main_exec_status . status ) ) ) ) {
2010-01-26 04:18:44 +01:00
2013-11-19 21:12:59 +01:00
r = service_arm_timer ( s , s - > restart_usec ) ;
2012-02-03 02:01:35 +01:00
if ( r < 0 )
2010-01-26 04:18:44 +01:00
goto fail ;
service_set_state ( s , SERVICE_AUTO_RESTART ) ;
2012-06-26 11:42:52 +02:00
}
2010-01-26 04:18:44 +01:00
2010-08-09 23:33:48 +02:00
s - > forbid_restart = false ;
2014-03-03 17:14:07 +01:00
/* We want fresh tmpdirs in case service is started again immediately */
2013-11-27 20:23:18 +01:00
exec_runtime_destroy ( s - > exec_runtime ) ;
s - > exec_runtime = exec_runtime_unref ( s - > exec_runtime ) ;
2013-03-14 18:12:27 +01:00
2014-03-03 17:14:07 +01:00
/* Also, remove the runtime directory in */
exec_context_destroy_runtime_directory ( & s - > exec_context , manager_get_runtime_prefix ( UNIT ( s ) - > manager ) ) ;
2013-08-28 19:27:44 +02:00
/* Try to delete the pid file. At this point it will be
* out - of - date , and some software might be confused by it , so
* let ' s remove it . */
if ( s - > pid_file )
unlink_noerrno ( s - > pid_file ) ;
2010-01-26 04:18:44 +01:00
return ;
fail :
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to run install restart timer: %m " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_dead ( s , SERVICE_FAILURE_RESOURCES , false ) ;
2010-01-26 04:18:44 +01:00
}
2012-02-03 02:01:35 +01:00
static void service_enter_stop_post ( Service * s , ServiceResult f ) {
2010-01-26 04:18:44 +01:00
int r ;
assert ( s ) ;
2012-02-03 02:01:35 +01:00
if ( f ! = SERVICE_SUCCESS )
s - > result = f ;
2010-01-26 04:18:44 +01:00
2010-04-11 00:22:36 +02:00
service_unwatch_control_pid ( s ) ;
2014-02-06 17:17:51 +01:00
unit_watch_all_pids ( UNIT ( s ) ) ;
2010-04-11 00:22:36 +02:00
2013-03-02 14:28:58 +01:00
s - > control_command = s - > exec_command [ SERVICE_EXEC_STOP_POST ] ;
if ( s - > control_command ) {
2011-01-20 18:46:38 +01:00
s - > control_command_id = SERVICE_EXEC_STOP_POST ;
2012-04-13 23:24:47 +02:00
r = service_spawn ( s ,
s - > control_command ,
2014-08-21 18:01:22 +02:00
s - > timeout_stop_usec ,
2012-04-13 23:24:47 +02:00
false ,
! s - > permissions_start_only ,
! s - > root_directory_start_only ,
true ,
true ,
& s - > control_pid ) ;
if ( r < 0 )
2010-01-26 04:18:44 +01:00
goto fail ;
2010-04-13 02:06:27 +02:00
service_set_state ( s , SERVICE_STOP_POST ) ;
} else
2014-01-29 14:58:04 +01:00
service_enter_signal ( s , SERVICE_FINAL_SIGTERM , SERVICE_SUCCESS ) ;
2010-01-26 04:18:44 +01:00
return ;
fail :
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to run 'stop-post' task: %m " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_FINAL_SIGTERM , SERVICE_FAILURE_RESOURCES ) ;
2010-01-26 04:18:44 +01:00
}
2012-02-03 02:01:35 +01:00
static void service_enter_signal ( Service * s , ServiceState state , ServiceResult f ) {
2010-01-26 04:18:44 +01:00
int r ;
assert ( s ) ;
2012-02-03 02:01:35 +01:00
if ( f ! = SERVICE_SUCCESS )
s - > result = f ;
2010-01-26 04:18:44 +01:00
2014-02-06 17:17:51 +01:00
unit_watch_all_pids ( UNIT ( s ) ) ;
2013-01-26 05:53:30 +01:00
r = unit_kill_context (
UNIT ( s ) ,
& s - > kill_context ,
2014-10-28 16:35:40 +01:00
( state ! = SERVICE_STOP_SIGTERM & & state ! = SERVICE_FINAL_SIGTERM & & state ! = SERVICE_STOP_SIGABRT ) ?
KILL_KILL : ( state = = SERVICE_STOP_SIGABRT ? KILL_ABORT : KILL_TERMINATE ) ,
2013-01-26 05:53:30 +01:00
s - > main_pid ,
s - > control_pid ,
s - > main_pid_alien ) ;
2014-01-29 14:58:04 +01:00
2013-01-26 05:53:30 +01:00
if ( r < 0 )
goto fail ;
2010-01-26 04:18:44 +01:00
2013-01-26 05:53:30 +01:00
if ( r > 0 ) {
2012-08-07 14:41:48 +02:00
if ( s - > timeout_stop_usec > 0 ) {
2013-11-19 21:12:59 +01:00
r = service_arm_timer ( s , s - > timeout_stop_usec ) ;
2012-08-07 14:41:48 +02:00
if ( r < 0 )
2010-04-23 20:28:33 +02:00
goto fail ;
2012-08-07 14:41:48 +02:00
}
2010-01-28 01:59:41 +01:00
2010-04-13 02:06:27 +02:00
service_set_state ( s , state ) ;
2014-10-28 16:35:40 +01:00
} else if ( state = = SERVICE_STOP_SIGTERM | | state = = SERVICE_STOP_SIGABRT )
2014-01-29 14:58:04 +01:00
service_enter_signal ( s , SERVICE_STOP_SIGKILL , SERVICE_SUCCESS ) ;
else if ( state = = SERVICE_STOP_SIGKILL )
2012-02-03 02:01:35 +01:00
service_enter_stop_post ( s , SERVICE_SUCCESS ) ;
2014-01-29 14:58:04 +01:00
else if ( state = = SERVICE_FINAL_SIGTERM )
service_enter_signal ( s , SERVICE_FINAL_SIGKILL , SERVICE_SUCCESS ) ;
2010-04-13 02:06:27 +02:00
else
2012-02-03 02:01:35 +01:00
service_enter_dead ( s , SERVICE_SUCCESS , true ) ;
2010-01-26 04:18:44 +01:00
return ;
fail :
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to kill processes: %m " , UNIT ( s ) - > id ) ;
2010-01-26 04:18:44 +01:00
2014-10-28 16:35:40 +01:00
if ( state = = SERVICE_STOP_SIGTERM | | state = = SERVICE_STOP_SIGKILL | |
state = = SERVICE_STOP_SIGABRT )
2012-02-03 02:01:35 +01:00
service_enter_stop_post ( s , SERVICE_FAILURE_RESOURCES ) ;
2010-01-26 04:18:44 +01:00
else
2012-02-03 02:01:35 +01:00
service_enter_dead ( s , SERVICE_FAILURE_RESOURCES , true ) ;
2010-01-26 04:18:44 +01:00
}
2014-08-21 17:03:15 +02:00
static void service_enter_stop_by_notify ( Service * s ) {
assert ( s ) ;
unit_watch_all_pids ( UNIT ( s ) ) ;
if ( s - > timeout_stop_usec > 0 )
service_arm_timer ( s , s - > timeout_stop_usec ) ;
2014-10-09 17:27:57 +02:00
/* The service told us it's stopping, so it's as if we SIGTERM'd it. */
service_set_state ( s , SERVICE_STOP_SIGTERM ) ;
2014-08-21 17:03:15 +02:00
}
2012-02-03 02:01:35 +01:00
static void service_enter_stop ( Service * s , ServiceResult f ) {
2010-01-26 04:18:44 +01:00
int r ;
2010-06-17 22:55:53 +02:00
2010-01-26 04:18:44 +01:00
assert ( s ) ;
2012-02-03 02:01:35 +01:00
if ( f ! = SERVICE_SUCCESS )
s - > result = f ;
2010-01-26 04:18:44 +01:00
2010-04-11 00:22:36 +02:00
service_unwatch_control_pid ( s ) ;
2014-02-06 17:17:51 +01:00
unit_watch_all_pids ( UNIT ( s ) ) ;
2010-04-11 00:22:36 +02:00
2013-03-02 14:28:58 +01:00
s - > control_command = s - > exec_command [ SERVICE_EXEC_STOP ] ;
if ( s - > control_command ) {
2011-01-20 18:46:38 +01:00
s - > control_command_id = SERVICE_EXEC_STOP ;
2012-04-13 23:24:47 +02:00
r = service_spawn ( s ,
s - > control_command ,
2014-08-21 18:01:22 +02:00
s - > timeout_stop_usec ,
2012-04-13 23:24:47 +02:00
false ,
! s - > permissions_start_only ,
! s - > root_directory_start_only ,
false ,
true ,
& s - > control_pid ) ;
if ( r < 0 )
2010-01-26 04:18:44 +01:00
goto fail ;
2010-04-13 02:06:27 +02:00
service_set_state ( s , SERVICE_STOP ) ;
} else
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_STOP_SIGTERM , SERVICE_SUCCESS ) ;
2010-01-26 04:18:44 +01:00
return ;
fail :
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to run 'stop' task: %m " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_STOP_SIGTERM , SERVICE_FAILURE_RESOURCES ) ;
2010-01-26 04:18:44 +01:00
}
2012-02-03 02:01:35 +01:00
static void service_enter_running ( Service * s , ServiceResult f ) {
2010-06-22 04:09:50 +02:00
int main_pid_ok , cgroup_ok ;
2010-04-13 02:06:27 +02:00
assert ( s ) ;
2012-02-03 02:01:35 +01:00
if ( f ! = SERVICE_SUCCESS )
s - > result = f ;
2010-04-13 02:06:27 +02:00
2010-06-22 04:09:50 +02:00
main_pid_ok = main_pid_good ( s ) ;
cgroup_ok = cgroup_good ( s ) ;
if ( ( main_pid_ok > 0 | | ( main_pid_ok < 0 & & cgroup_ok ! = 0 ) ) & &
2014-08-21 17:03:15 +02:00
( s - > bus_name_good | | s - > type ! = SERVICE_DBUS ) ) {
/* If there are any queued up sd_notify()
* notifications , process them now */
if ( s - > notify_state = = NOTIFY_RELOADING )
service_enter_reload_by_notify ( s ) ;
else if ( s - > notify_state = = NOTIFY_STOPPING )
service_enter_stop_by_notify ( s ) ;
else
service_set_state ( s , SERVICE_RUNNING ) ;
} else if ( s - > remain_after_exit )
2010-04-13 02:06:27 +02:00
service_set_state ( s , SERVICE_EXITED ) ;
else
2012-02-03 02:01:35 +01:00
service_enter_stop ( s , SERVICE_SUCCESS ) ;
2010-04-13 02:06:27 +02:00
}
2010-01-26 04:18:44 +01:00
static void service_enter_start_post ( Service * s ) {
int r ;
assert ( s ) ;
2010-04-11 00:22:36 +02:00
service_unwatch_control_pid ( s ) ;
2013-12-11 20:49:43 +01:00
service_reset_watchdog ( s ) ;
2012-02-08 10:10:34 +01:00
2013-03-02 14:28:58 +01:00
s - > control_command = s - > exec_command [ SERVICE_EXEC_START_POST ] ;
if ( s - > control_command ) {
2011-01-20 18:46:38 +01:00
s - > control_command_id = SERVICE_EXEC_START_POST ;
2012-04-13 23:24:47 +02:00
r = service_spawn ( s ,
s - > control_command ,
2014-08-21 18:01:22 +02:00
s - > timeout_start_usec ,
2012-04-13 23:24:47 +02:00
false ,
! s - > permissions_start_only ,
! s - > root_directory_start_only ,
false ,
true ,
& s - > control_pid ) ;
if ( r < 0 )
2010-01-26 04:18:44 +01:00
goto fail ;
2010-04-13 02:06:27 +02:00
service_set_state ( s , SERVICE_START_POST ) ;
} else
2012-02-03 02:01:35 +01:00
service_enter_running ( s , SERVICE_SUCCESS ) ;
2010-01-26 04:18:44 +01:00
return ;
fail :
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to run 'start-post' task: %m " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_stop ( s , SERVICE_FAILURE_RESOURCES ) ;
2010-01-26 04:18:44 +01:00
}
2013-06-27 04:14:27 +02:00
static void service_kill_control_processes ( Service * s ) {
char * p ;
if ( ! UNIT ( s ) - > cgroup_path )
return ;
2015-02-03 02:05:59 +01:00
p = strjoina ( UNIT ( s ) - > cgroup_path , " /control " ) ;
2013-06-27 04:14:27 +02:00
cg_kill_recursive ( SYSTEMD_CGROUP_CONTROLLER , p , SIGKILL , true , true , true , NULL ) ;
}
2010-01-26 04:18:44 +01:00
static void service_enter_start ( Service * s ) {
2013-06-27 04:14:27 +02:00
ExecCommand * c ;
2010-01-26 04:18:44 +01:00
pid_t pid ;
int r ;
assert ( s ) ;
2013-08-09 16:40:57 +02:00
service_unwatch_control_pid ( s ) ;
service_unwatch_main_pid ( s ) ;
2010-04-13 02:06:27 +02:00
2012-01-11 01:51:32 +01:00
/* We want to ensure that nobody leaks processes from
* START_PRE here , so let ' s go on a killing spree , People
* should not spawn long running processes from START_PRE . */
2013-06-27 04:14:27 +02:00
service_kill_control_processes ( s ) ;
2012-01-11 01:51:32 +01:00
2011-01-20 18:46:38 +01:00
if ( s - > type = = SERVICE_FORKING ) {
s - > control_command_id = SERVICE_EXEC_START ;
c = s - > control_command = s - > exec_command [ SERVICE_EXEC_START ] ;
s - > main_command = NULL ;
} else {
s - > control_command_id = _SERVICE_EXEC_COMMAND_INVALID ;
s - > control_command = NULL ;
c = s - > main_command = s - > exec_command [ SERVICE_EXEC_START ] ;
}
2010-08-13 18:23:01 +02:00
2014-08-21 18:50:42 +02:00
if ( ! c ) {
assert ( s - > type = = SERVICE_ONESHOT ) ;
service_enter_start_post ( s ) ;
return ;
}
2012-04-13 23:24:47 +02:00
r = service_spawn ( s ,
c ,
2014-08-21 18:01:22 +02:00
IN_SET ( s - > type , SERVICE_FORKING , SERVICE_DBUS , SERVICE_NOTIFY , SERVICE_ONESHOT ) ? s - > timeout_start_usec : 0 ,
2012-04-13 23:24:47 +02:00
true ,
true ,
true ,
true ,
false ,
& pid ) ;
if ( r < 0 )
2010-01-26 04:18:44 +01:00
goto fail ;
2012-04-24 14:28:00 +02:00
if ( s - > type = = SERVICE_SIMPLE | | s - > type = = SERVICE_IDLE ) {
2010-01-26 04:18:44 +01:00
/* For simple services we immediately start
* the START_POST binaries . */
2010-06-17 22:55:53 +02:00
service_set_main_pid ( s , pid ) ;
2010-01-26 04:18:44 +01:00
service_enter_start_post ( s ) ;
} else if ( s - > type = = SERVICE_FORKING ) {
/* For forking services we wait until the start
* process exited . */
2010-06-18 22:05:29 +02:00
s - > control_pid = pid ;
2010-04-13 02:06:27 +02:00
service_set_state ( s , SERVICE_START ) ;
2010-08-13 18:23:01 +02:00
} else if ( s - > type = = SERVICE_ONESHOT | |
2010-06-16 05:10:31 +02:00
s - > type = = SERVICE_DBUS | |
s - > type = = SERVICE_NOTIFY ) {
2010-01-30 02:07:35 +01:00
2010-08-13 18:23:01 +02:00
/* For oneshot services we wait until the start
2010-01-30 02:07:35 +01:00
* process exited , too , but it is our main process . */
2010-04-15 23:16:16 +02:00
/* For D-Bus services we know the main pid right away,
2010-06-16 05:10:31 +02:00
* but wait for the bus name to appear on the
* bus . Notify services are similar . */
2010-04-15 23:16:16 +02:00
2010-06-17 22:55:53 +02:00
service_set_main_pid ( s , pid ) ;
2010-04-13 02:06:27 +02:00
service_set_state ( s , SERVICE_START ) ;
2010-01-26 04:18:44 +01:00
} else
assert_not_reached ( " Unknown service type " ) ;
return ;
fail :
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to run 'start' task: %m " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_FINAL_SIGTERM , SERVICE_FAILURE_RESOURCES ) ;
2010-01-26 04:18:44 +01:00
}
static void service_enter_start_pre ( Service * s ) {
int r ;
assert ( s ) ;
2010-04-11 00:22:36 +02:00
service_unwatch_control_pid ( s ) ;
2013-03-02 14:28:58 +01:00
s - > control_command = s - > exec_command [ SERVICE_EXEC_START_PRE ] ;
if ( s - > control_command ) {
2012-01-11 01:51:32 +01:00
/* Before we start anything, let's clear up what might
* be left from previous runs . */
2013-06-27 04:14:27 +02:00
service_kill_control_processes ( s ) ;
2012-01-11 01:51:32 +01:00
2011-01-20 18:46:38 +01:00
s - > control_command_id = SERVICE_EXEC_START_PRE ;
2012-04-13 23:24:47 +02:00
r = service_spawn ( s ,
s - > control_command ,
2014-08-21 18:01:22 +02:00
s - > timeout_start_usec ,
2012-04-13 23:24:47 +02:00
false ,
! s - > permissions_start_only ,
! s - > root_directory_start_only ,
true ,
true ,
& s - > control_pid ) ;
if ( r < 0 )
2010-01-26 04:18:44 +01:00
goto fail ;
2010-04-13 02:06:27 +02:00
service_set_state ( s , SERVICE_START_PRE ) ;
} else
2010-01-26 04:18:44 +01:00
service_enter_start ( s ) ;
return ;
fail :
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to run 'start-pre' task: %m " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_dead ( s , SERVICE_FAILURE_RESOURCES , true ) ;
2010-01-26 04:18:44 +01:00
}
static void service_enter_restart ( Service * s ) {
2013-11-19 21:12:59 +01:00
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL ;
2010-01-26 04:18:44 +01:00
int r ;
2010-07-08 02:43:18 +02:00
2010-01-26 04:18:44 +01:00
assert ( s ) ;
2012-07-18 02:28:08 +02:00
if ( UNIT ( s ) - > job & & UNIT ( s ) - > job - > type = = JOB_STOP ) {
/* Don't restart things if we are going down anyway */
2014-11-27 20:20:23 +01:00
log_unit_info ( UNIT ( s ) - > id , " Stop job pending for unit, delaying automatic restart. " ) ;
2010-11-01 17:50:43 +01:00
2013-11-19 21:12:59 +01:00
r = service_arm_timer ( s , s - > restart_usec ) ;
2012-07-18 02:28:08 +02:00
if ( r < 0 )
2010-11-01 17:50:43 +01:00
goto fail ;
2012-04-29 15:35:40 +02:00
return ;
2010-11-01 17:50:43 +01:00
}
2012-04-03 05:45:35 +02:00
/* Any units that are bound to this service must also be
* restarted . We use JOB_RESTART ( instead of the more obvious
* JOB_START ) here so that those dependency jobs will be added
* as well . */
r = manager_add_job ( UNIT ( s ) - > manager , JOB_RESTART , UNIT ( s ) , JOB_FAIL , false , & error , NULL ) ;
if ( r < 0 )
2010-01-26 04:18:44 +01:00
goto fail ;
2012-07-18 02:28:08 +02:00
/* Note that we stay in the SERVICE_AUTO_RESTART state here,
* it will be canceled as part of the service_stop ( ) call that
* is executed as part of JOB_RESTART . */
2014-11-27 20:20:23 +01:00
log_unit_debug ( UNIT ( s ) - > id , " %s scheduled restart job. " , UNIT ( s ) - > id ) ;
2010-01-26 04:18:44 +01:00
return ;
fail :
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s failed to schedule restart job: %s " , UNIT ( s ) - > id , bus_error_message ( & error , - r ) ) ;
2012-02-03 02:01:35 +01:00
service_enter_dead ( s , SERVICE_FAILURE_RESOURCES , false ) ;
2010-01-26 04:18:44 +01:00
}
2014-08-21 17:03:15 +02:00
static void service_enter_reload_by_notify ( Service * s ) {
assert ( s ) ;
if ( s - > timeout_start_usec > 0 )
service_arm_timer ( s , s - > timeout_start_usec ) ;
service_set_state ( s , SERVICE_RELOAD ) ;
}
2010-01-26 04:18:44 +01:00
static void service_enter_reload ( Service * s ) {
int r ;
assert ( s ) ;
2010-04-11 00:22:36 +02:00
service_unwatch_control_pid ( s ) ;
2013-03-02 14:28:58 +01:00
s - > control_command = s - > exec_command [ SERVICE_EXEC_RELOAD ] ;
if ( s - > control_command ) {
2011-01-20 18:46:38 +01:00
s - > control_command_id = SERVICE_EXEC_RELOAD ;
2012-04-13 23:24:47 +02:00
r = service_spawn ( s ,
s - > control_command ,
2014-08-21 18:01:22 +02:00
s - > timeout_start_usec ,
2012-04-13 23:24:47 +02:00
false ,
! s - > permissions_start_only ,
! s - > root_directory_start_only ,
false ,
true ,
& s - > control_pid ) ;
if ( r < 0 )
2010-01-26 04:18:44 +01:00
goto fail ;
2010-04-13 02:06:27 +02:00
service_set_state ( s , SERVICE_RELOAD ) ;
} else
2012-02-03 02:01:35 +01:00
service_enter_running ( s , SERVICE_SUCCESS ) ;
2010-01-26 04:18:44 +01:00
return ;
fail :
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to run 'reload' task: %m " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
s - > reload_result = SERVICE_FAILURE_RESOURCES ;
service_enter_running ( s , SERVICE_SUCCESS ) ;
2010-01-26 04:18:44 +01:00
}
2012-02-03 02:01:35 +01:00
static void service_run_next_control ( Service * s ) {
2010-01-26 04:18:44 +01:00
int r ;
assert ( s ) ;
assert ( s - > control_command ) ;
assert ( s - > control_command - > command_next ) ;
2010-08-13 18:23:01 +02:00
assert ( s - > control_command_id ! = SERVICE_EXEC_START ) ;
2010-01-26 04:18:44 +01:00
2010-08-13 18:23:01 +02:00
s - > control_command = s - > control_command - > command_next ;
2010-04-11 00:22:36 +02:00
service_unwatch_control_pid ( s ) ;
2012-04-13 23:24:47 +02:00
r = service_spawn ( s ,
s - > control_command ,
2014-08-21 18:01:22 +02:00
IN_SET ( s - > state , SERVICE_START_PRE , SERVICE_START , SERVICE_START_POST , SERVICE_RUNNING , SERVICE_RELOAD ) ? s - > timeout_start_usec : s - > timeout_stop_usec ,
2012-04-13 23:24:47 +02:00
false ,
! s - > permissions_start_only ,
! s - > root_directory_start_only ,
s - > control_command_id = = SERVICE_EXEC_START_PRE | |
s - > control_command_id = = SERVICE_EXEC_STOP_POST ,
true ,
& s - > control_pid ) ;
if ( r < 0 )
2010-01-26 04:18:44 +01:00
goto fail ;
return ;
fail :
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to run next control task: %m " , UNIT ( s ) - > id ) ;
2010-01-26 04:18:44 +01:00
2010-04-13 02:06:27 +02:00
if ( s - > state = = SERVICE_START_PRE )
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_FINAL_SIGTERM , SERVICE_FAILURE_RESOURCES ) ;
2010-04-13 02:06:27 +02:00
else if ( s - > state = = SERVICE_STOP )
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_STOP_SIGTERM , SERVICE_FAILURE_RESOURCES ) ;
2010-01-26 04:18:44 +01:00
else if ( s - > state = = SERVICE_STOP_POST )
2012-02-03 02:01:35 +01:00
service_enter_dead ( s , SERVICE_FAILURE_RESOURCES , true ) ;
2011-01-20 13:17:22 +01:00
else if ( s - > state = = SERVICE_RELOAD ) {
2012-02-03 02:01:35 +01:00
s - > reload_result = SERVICE_FAILURE_RESOURCES ;
service_enter_running ( s , SERVICE_SUCCESS ) ;
2011-01-20 13:17:22 +01:00
} else
2012-02-03 02:01:35 +01:00
service_enter_stop ( s , SERVICE_FAILURE_RESOURCES ) ;
2010-01-23 01:52:57 +01:00
}
2012-02-03 02:01:35 +01:00
static void service_run_next_main ( Service * s ) {
2010-08-13 18:23:01 +02:00
pid_t pid ;
int r ;
assert ( s ) ;
2011-01-20 18:46:38 +01:00
assert ( s - > main_command ) ;
assert ( s - > main_command - > command_next ) ;
assert ( s - > type = = SERVICE_ONESHOT ) ;
2010-08-13 18:23:01 +02:00
2011-01-20 18:46:38 +01:00
s - > main_command = s - > main_command - > command_next ;
2010-08-13 18:23:01 +02:00
service_unwatch_main_pid ( s ) ;
2012-04-13 23:24:47 +02:00
r = service_spawn ( s ,
s - > main_command ,
2014-08-21 18:01:22 +02:00
s - > timeout_start_usec ,
2012-04-13 23:24:47 +02:00
true ,
true ,
true ,
true ,
false ,
& pid ) ;
if ( r < 0 )
2010-08-13 18:23:01 +02:00
goto fail ;
service_set_main_pid ( s , pid ) ;
return ;
fail :
2014-11-28 13:17:02 +01:00
log_unit_warning_errno ( UNIT ( s ) - > id , r , " %s failed to run next main task: %m " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_stop ( s , SERVICE_FAILURE_RESOURCES ) ;
2010-08-13 18:23:01 +02:00
}
2014-04-24 09:35:37 +02:00
static int service_start_limit_test ( Service * s ) {
assert ( s ) ;
if ( ratelimit_test ( & s - > start_limit ) )
return 0 ;
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " start request repeated too quickly for %s " , UNIT ( s ) - > id ) ;
2014-08-22 16:36:38 +02:00
return failure_action ( UNIT ( s ) - > manager , s - > start_limit_action , s - > reboot_arg ) ;
2014-04-24 09:35:37 +02:00
}
2010-01-26 21:39:06 +01:00
static int service_start ( Unit * u ) {
Service * s = SERVICE ( u ) ;
2012-02-09 13:05:23 +01:00
int r ;
2010-01-23 01:52:57 +01:00
assert ( s ) ;
2010-01-26 04:18:44 +01:00
/* We cannot fulfill this request right now, try again later
* please ! */
if ( s - > state = = SERVICE_STOP | |
2014-10-28 16:35:40 +01:00
s - > state = = SERVICE_STOP_SIGABRT | |
2010-01-26 04:18:44 +01:00
s - > state = = SERVICE_STOP_SIGTERM | |
s - > state = = SERVICE_STOP_SIGKILL | |
s - > state = = SERVICE_STOP_POST | |
s - > state = = SERVICE_FINAL_SIGTERM | |
s - > state = = SERVICE_FINAL_SIGKILL )
2010-01-23 01:52:57 +01:00
return - EAGAIN ;
2010-01-26 04:18:44 +01:00
/* Already on it! */
if ( s - > state = = SERVICE_START_PRE | |
s - > state = = SERVICE_START | |
s - > state = = SERVICE_START_POST )
return 0 ;
2012-04-29 15:35:51 +02:00
/* A service that will be restarted must be stopped first to
2012-07-13 23:34:40 +02:00
* trigger BindsTo and / or OnFailure dependencies . If a user
2012-04-29 15:35:51 +02:00
* does not want to wait for the holdoff time to elapse , the
2012-07-18 02:42:43 +02:00
* service should be manually restarted , not started . We
* simply return EAGAIN here , so that any start jobs stay
* queued , and assume that the auto restart timer will
* eventually trigger the restart . */
if ( s - > state = = SERVICE_AUTO_RESTART )
2012-07-18 02:28:08 +02:00
return - EAGAIN ;
2012-04-29 15:35:51 +02:00
assert ( s - > state = = SERVICE_DEAD | | s - > state = = SERVICE_FAILED ) ;
2010-01-23 01:52:57 +01:00
2010-01-29 04:42:57 +01:00
/* Make sure we don't enter a busy loop of some kind. */
2012-02-09 13:05:23 +01:00
r = service_start_limit_test ( s ) ;
2012-03-05 22:47:54 +01:00
if ( r < 0 ) {
2012-08-22 05:02:33 +02:00
service_enter_dead ( s , SERVICE_FAILURE_START_LIMIT , false ) ;
2012-02-09 13:05:23 +01:00
return r ;
2012-03-05 22:47:54 +01:00
}
2010-01-29 04:42:57 +01:00
2012-02-03 02:01:35 +01:00
s - > result = SERVICE_SUCCESS ;
s - > reload_result = SERVICE_SUCCESS ;
2010-01-26 04:18:44 +01:00
s - > main_pid_known = false ;
2011-04-28 04:56:53 +02:00
s - > main_pid_alien = false ;
2010-08-09 23:33:48 +02:00
s - > forbid_restart = false ;
2015-03-01 16:24:19 +01:00
s - > reset_cpu_usage = true ;
2010-01-26 04:18:44 +01:00
2014-07-07 17:33:46 +02:00
free ( s - > status_text ) ;
s - > status_text = NULL ;
s - > status_errno = 0 ;
2014-08-21 17:03:15 +02:00
s - > notify_state = NOTIFY_UNKNOWN ;
2010-01-26 04:18:44 +01:00
service_enter_start_pre ( s ) ;
2015-01-28 15:07:13 +01:00
return 1 ;
2010-01-23 01:52:57 +01:00
}
2010-01-26 21:39:06 +01:00
static int service_stop ( Unit * u ) {
Service * s = SERVICE ( u ) ;
2010-01-23 01:52:57 +01:00
assert ( s ) ;
2012-04-29 15:35:48 +02:00
/* Don't create restart jobs from here. */
2010-08-09 23:33:48 +02:00
s - > forbid_restart = true ;
2010-01-26 04:18:44 +01:00
2010-04-10 17:53:17 +02:00
/* Already on it */
if ( s - > state = = SERVICE_STOP | |
2014-10-28 16:35:40 +01:00
s - > state = = SERVICE_STOP_SIGABRT | |
2010-04-10 17:53:17 +02:00
s - > state = = SERVICE_STOP_SIGTERM | |
s - > state = = SERVICE_STOP_SIGKILL | |
s - > state = = SERVICE_STOP_POST | |
s - > state = = SERVICE_FINAL_SIGTERM | |
s - > state = = SERVICE_FINAL_SIGKILL )
return 0 ;
2012-04-29 15:35:48 +02:00
/* A restart will be scheduled or is in progress. */
2010-01-26 04:18:44 +01:00
if ( s - > state = = SERVICE_AUTO_RESTART ) {
2012-06-26 11:42:52 +02:00
service_set_state ( s , SERVICE_DEAD ) ;
2010-01-26 04:18:44 +01:00
return 0 ;
}
2010-07-10 04:52:00 +02:00
/* If there's already something running we go directly into
* kill mode . */
if ( s - > state = = SERVICE_START_PRE | |
s - > state = = SERVICE_START | |
s - > state = = SERVICE_START_POST | |
s - > state = = SERVICE_RELOAD ) {
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_STOP_SIGTERM , SERVICE_SUCCESS ) ;
2010-07-10 04:52:00 +02:00
return 0 ;
}
2010-01-23 01:52:57 +01:00
2010-07-10 04:52:00 +02:00
assert ( s - > state = = SERVICE_RUNNING | |
s - > state = = SERVICE_EXITED ) ;
2010-04-23 22:55:14 +02:00
2012-02-03 02:01:35 +01:00
service_enter_stop ( s , SERVICE_SUCCESS ) ;
2015-01-28 15:07:13 +01:00
return 1 ;
2010-01-23 01:52:57 +01:00
}
2010-01-26 21:39:06 +01:00
static int service_reload ( Unit * u ) {
Service * s = SERVICE ( u ) ;
2010-01-26 04:18:44 +01:00
assert ( s ) ;
2010-04-13 02:06:27 +02:00
assert ( s - > state = = SERVICE_RUNNING | | s - > state = = SERVICE_EXITED ) ;
2010-01-26 04:18:44 +01:00
service_enter_reload ( s ) ;
2010-01-23 01:52:57 +01:00
return 0 ;
}
2013-05-03 04:51:50 +02:00
_pure_ static bool service_can_reload ( Unit * u ) {
2010-01-26 21:39:06 +01:00
Service * s = SERVICE ( u ) ;
2010-01-26 04:18:44 +01:00
assert ( s ) ;
return ! ! s - > exec_command [ SERVICE_EXEC_RELOAD ] ;
}
2010-04-21 03:27:44 +02:00
static int service_serialize ( Unit * u , FILE * f , FDSet * fds ) {
Service * s = SERVICE ( u ) ;
2015-01-07 01:18:13 +01:00
ServiceFDStore * fs ;
2010-04-21 03:27:44 +02:00
assert ( u ) ;
assert ( f ) ;
assert ( fds ) ;
unit_serialize_item ( u , f , " state " , service_state_to_string ( s - > state ) ) ;
2012-02-03 02:01:35 +01:00
unit_serialize_item ( u , f , " result " , service_result_to_string ( s - > result ) ) ;
unit_serialize_item ( u , f , " reload-result " , service_result_to_string ( s - > reload_result ) ) ;
2010-04-21 03:27:44 +02:00
if ( s - > control_pid > 0 )
2013-12-30 23:22:26 +01:00
unit_serialize_item_format ( u , f , " control-pid " , PID_FMT ,
s - > control_pid ) ;
2010-04-21 03:27:44 +02:00
2010-06-17 22:55:53 +02:00
if ( s - > main_pid_known & & s - > main_pid > 0 )
2013-12-30 23:22:26 +01:00
unit_serialize_item_format ( u , f , " main-pid " , PID_FMT , s - > main_pid ) ;
2010-04-21 03:27:44 +02:00
unit_serialize_item ( u , f , " main-pid-known " , yes_no ( s - > main_pid_known ) ) ;
2010-07-21 05:16:45 +02:00
if ( s - > status_text )
unit_serialize_item ( u , f , " status-text " , s - > status_text ) ;
2012-02-03 02:31:54 +01:00
/* FIXME: There's a minor uncleanliness here: if there are
* multiple commands attached here , we will start from the
* first one again */
2010-04-21 03:27:44 +02:00
if ( s - > control_command_id > = 0 )
2013-03-02 14:28:58 +01:00
unit_serialize_item ( u , f , " control-command " ,
service_exec_command_to_string ( s - > control_command_id ) ) ;
2010-04-21 03:27:44 +02:00
if ( s - > socket_fd > = 0 ) {
int copy ;
2015-01-07 01:18:13 +01:00
copy = fdset_put_dup ( fds , s - > socket_fd ) ;
if ( copy < 0 )
2010-04-21 03:27:44 +02:00
return copy ;
unit_serialize_item_format ( u , f , " socket-fd " , " %i " , copy ) ;
}
2014-08-22 19:02:03 +02:00
if ( s - > bus_endpoint_fd > = 0 ) {
int copy ;
2015-01-07 01:18:13 +01:00
copy = fdset_put_dup ( fds , s - > bus_endpoint_fd ) ;
if ( copy < 0 )
2014-08-22 19:02:03 +02:00
return copy ;
unit_serialize_item_format ( u , f , " endpoint-fd " , " %i " , copy ) ;
}
2015-01-07 01:18:13 +01:00
LIST_FOREACH ( fd_store , fs , s - > fd_store ) {
int copy ;
copy = fdset_put_dup ( fds , fs - > fd ) ;
if ( copy < 0 )
return copy ;
unit_serialize_item_format ( u , f , " fd-store-fd " , " %i " , copy ) ;
}
2010-07-07 04:12:59 +02:00
if ( s - > main_exec_status . pid > 0 ) {
2013-12-30 23:22:26 +01:00
unit_serialize_item_format ( u , f , " main-exec-status-pid " , PID_FMT ,
s - > main_exec_status . pid ) ;
2013-03-02 14:28:58 +01:00
dual_timestamp_serialize ( f , " main-exec-status-start " ,
& s - > main_exec_status . start_timestamp ) ;
dual_timestamp_serialize ( f , " main-exec-status-exit " ,
& s - > main_exec_status . exit_timestamp ) ;
2010-07-07 04:12:59 +02:00
2010-10-28 03:16:03 +02:00
if ( dual_timestamp_is_set ( & s - > main_exec_status . exit_timestamp ) ) {
2013-03-02 14:28:58 +01:00
unit_serialize_item_format ( u , f , " main-exec-status-code " , " %i " ,
s - > main_exec_status . code ) ;
unit_serialize_item_format ( u , f , " main-exec-status-status " , " %i " ,
s - > main_exec_status . status ) ;
2010-07-07 04:12:59 +02:00
}
}
2012-02-01 17:17:12 +01:00
if ( dual_timestamp_is_set ( & s - > watchdog_timestamp ) )
2013-12-11 20:49:43 +01:00
dual_timestamp_serialize ( f , " watchdog-timestamp " , & s - > watchdog_timestamp ) ;
2010-07-07 04:12:59 +02:00
2013-10-07 05:06:35 +02:00
if ( s - > forbid_restart )
2013-10-09 00:13:55 +02:00
unit_serialize_item ( u , f , " forbid-restart " , yes_no ( s - > forbid_restart ) ) ;
2013-10-07 05:06:35 +02:00
2010-04-21 03:27:44 +02:00
return 0 ;
}
static int service_deserialize_item ( Unit * u , const char * key , const char * value , FDSet * fds ) {
Service * s = SERVICE ( u ) ;
2015-01-07 01:18:13 +01:00
int r ;
2010-04-21 03:27:44 +02:00
assert ( u ) ;
assert ( key ) ;
assert ( value ) ;
assert ( fds ) ;
if ( streq ( key , " state " ) ) {
ServiceState state ;
2013-03-02 14:28:58 +01:00
state = service_state_from_string ( value ) ;
if ( state < 0 )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse state value %s " , value ) ;
2010-04-21 03:27:44 +02:00
else
s - > deserialized_state = state ;
2012-02-03 02:01:35 +01:00
} else if ( streq ( key , " result " ) ) {
ServiceResult f ;
f = service_result_from_string ( value ) ;
if ( f < 0 )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse result value %s " , value ) ;
2012-02-03 02:01:35 +01:00
else if ( f ! = SERVICE_SUCCESS )
s - > result = f ;
} else if ( streq ( key , " reload-result " ) ) {
ServiceResult f ;
f = service_result_from_string ( value ) ;
if ( f < 0 )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse reload result value %s " , value ) ;
2012-02-03 02:01:35 +01:00
else if ( f ! = SERVICE_SUCCESS )
s - > reload_result = f ;
2010-04-21 03:27:44 +02:00
} else if ( streq ( key , " control-pid " ) ) {
2010-06-17 22:55:53 +02:00
pid_t pid ;
2010-04-21 03:27:44 +02:00
2010-08-11 22:04:22 +02:00
if ( parse_pid ( value , & pid ) < 0 )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse control-pid value %s " , value ) ;
2010-04-21 03:27:44 +02:00
else
2010-06-18 22:05:29 +02:00
s - > control_pid = pid ;
2010-04-21 03:27:44 +02:00
} else if ( streq ( key , " main-pid " ) ) {
2010-06-17 22:55:53 +02:00
pid_t pid ;
2010-04-21 03:27:44 +02:00
2010-08-11 22:04:22 +02:00
if ( parse_pid ( value , & pid ) < 0 )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse main-pid value %s " , value ) ;
2013-10-01 05:06:56 +02:00
else {
service_set_main_pid ( s , pid ) ;
unit_watch_pid ( UNIT ( s ) , pid ) ;
}
2010-04-21 03:27:44 +02:00
} else if ( streq ( key , " main-pid-known " ) ) {
int b ;
2013-03-02 14:28:58 +01:00
b = parse_boolean ( value ) ;
if ( b < 0 )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse main-pid-known value %s " , value ) ;
2010-04-21 03:27:44 +02:00
else
s - > main_pid_known = b ;
2010-07-21 05:16:45 +02:00
} else if ( streq ( key , " status-text " ) ) {
char * t ;
2013-03-02 14:28:58 +01:00
t = strdup ( value ) ;
if ( ! t )
log_oom ( ) ;
else {
2010-07-21 05:16:45 +02:00
free ( s - > status_text ) ;
s - > status_text = t ;
}
2010-04-21 03:27:44 +02:00
} else if ( streq ( key , " control-command " ) ) {
ServiceExecCommand id ;
2013-03-02 14:28:58 +01:00
id = service_exec_command_from_string ( value ) ;
if ( id < 0 )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse exec-command value %s " , value ) ;
2010-04-21 03:27:44 +02:00
else {
s - > control_command_id = id ;
s - > control_command = s - > exec_command [ id ] ;
}
} else if ( streq ( key , " socket-fd " ) ) {
int fd ;
if ( safe_atoi ( value , & fd ) < 0 | | fd < 0 | | ! fdset_contains ( fds , fd ) )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse socket-fd value %s " , value ) ;
2010-04-21 03:27:44 +02:00
else {
2014-05-13 23:22:13 +02:00
asynchronous_close ( s - > socket_fd ) ;
2010-04-21 03:27:44 +02:00
s - > socket_fd = fdset_remove ( fds , fd ) ;
}
2014-08-22 19:02:03 +02:00
} else if ( streq ( key , " endpoint-fd " ) ) {
int fd ;
if ( safe_atoi ( value , & fd ) < 0 | | fd < 0 | | ! fdset_contains ( fds , fd ) )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse endpoint-fd value %s " , value ) ;
2014-08-22 19:02:03 +02:00
else {
safe_close ( s - > bus_endpoint_fd ) ;
s - > bus_endpoint_fd = fdset_remove ( fds , fd ) ;
}
2015-01-07 01:18:13 +01:00
} else if ( streq ( key , " fd-store-fd " ) ) {
int fd ;
if ( safe_atoi ( value , & fd ) < 0 | | fd < 0 | | ! fdset_contains ( fds , fd ) )
log_unit_debug ( u - > id , " Failed to parse fd-store-fd value %s " , value ) ;
else {
r = service_add_fd_store ( s , fd ) ;
if ( r < 0 )
log_unit_error_errno ( u - > id , r , " Failed to add fd to store: %m " ) ;
else if ( r > 0 )
fdset_remove ( fds , fd ) ;
}
2010-07-07 04:12:59 +02:00
} else if ( streq ( key , " main-exec-status-pid " ) ) {
pid_t pid ;
2010-08-11 22:04:22 +02:00
if ( parse_pid ( value , & pid ) < 0 )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse main-exec-status-pid value %s " , value ) ;
2010-07-07 04:12:59 +02:00
else
s - > main_exec_status . pid = pid ;
} else if ( streq ( key , " main-exec-status-code " ) ) {
int i ;
2010-08-11 22:04:22 +02:00
if ( safe_atoi ( value , & i ) < 0 )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse main-exec-status-code value %s " , value ) ;
2010-07-07 04:12:59 +02:00
else
s - > main_exec_status . code = i ;
} else if ( streq ( key , " main-exec-status-status " ) ) {
int i ;
2010-08-11 22:04:22 +02:00
if ( safe_atoi ( value , & i ) < 0 )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse main-exec-status-status value %s " , value ) ;
2010-07-07 04:12:59 +02:00
else
s - > main_exec_status . status = i ;
2010-10-28 03:16:03 +02:00
} else if ( streq ( key , " main-exec-status-start " ) )
dual_timestamp_deserialize ( value , & s - > main_exec_status . start_timestamp ) ;
else if ( streq ( key , " main-exec-status-exit " ) )
dual_timestamp_deserialize ( value , & s - > main_exec_status . exit_timestamp ) ;
2012-02-01 17:17:12 +01:00
else if ( streq ( key , " watchdog-timestamp " ) )
dual_timestamp_deserialize ( value , & s - > watchdog_timestamp ) ;
2013-11-27 20:23:18 +01:00
else if ( streq ( key , " forbid-restart " ) ) {
2013-10-07 05:06:35 +02:00
int b ;
b = parse_boolean ( value ) ;
if ( b < 0 )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Failed to parse forbid-restart value %s " , value ) ;
2013-10-07 05:06:35 +02:00
else
s - > forbid_restart = b ;
2013-03-14 18:12:27 +01:00
} else
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " Unknown serialization key '%s' " , key ) ;
2010-04-21 03:27:44 +02:00
return 0 ;
}
2013-05-03 04:51:50 +02:00
_pure_ static UnitActiveState service_active_state ( Unit * u ) {
2012-05-24 02:22:35 +02:00
const UnitActiveState * table ;
2010-01-26 21:39:06 +01:00
assert ( u ) ;
2010-01-23 01:52:57 +01:00
2012-05-24 02:22:35 +02:00
table = SERVICE ( u ) - > type = = SERVICE_IDLE ? state_translation_table_idle : state_translation_table ;
return table [ SERVICE ( u ) - > state ] ;
2010-01-26 04:18:44 +01:00
}
2010-04-13 20:59:01 +02:00
static const char * service_sub_state_to_string ( Unit * u ) {
assert ( u ) ;
return service_state_to_string ( SERVICE ( u ) - > state ) ;
}
2010-04-21 06:01:13 +02:00
static bool service_check_gc ( Unit * u ) {
Service * s = SERVICE ( u ) ;
assert ( s ) ;
2011-02-25 01:49:10 +01:00
/* Never clean up services that still have a process around,
* even if the service is formally dead . */
if ( cgroup_good ( s ) > 0 | |
main_pid_good ( s ) > 0 | |
control_pid_good ( s ) > 0 )
return true ;
return false ;
}
2013-05-03 04:51:50 +02:00
_pure_ static bool service_check_snapshot ( Unit * u ) {
2010-04-21 06:01:13 +02:00
Service * s = SERVICE ( u ) ;
assert ( s ) ;
2014-08-21 16:19:25 +02:00
return s - > socket_fd < 0 ;
2010-04-21 06:01:13 +02:00
}
2011-12-03 02:13:30 +01:00
static int service_retry_pid_file ( Service * s ) {
int r ;
assert ( s - > pid_file ) ;
assert ( s - > state = = SERVICE_START | | s - > state = = SERVICE_START_POST ) ;
r = service_load_pid_file ( s , false ) ;
if ( r < 0 )
return r ;
service_unwatch_pid_file ( s ) ;
2012-02-03 02:01:35 +01:00
service_enter_running ( s , SERVICE_SUCCESS ) ;
2011-12-03 02:13:30 +01:00
return 0 ;
}
static int service_watch_pid_file ( Service * s ) {
int r ;
2014-11-27 20:20:23 +01:00
log_unit_debug ( UNIT ( s ) - > id , " Setting watch for %s's PID file %s " , UNIT ( s ) - > id , s - > pid_file_pathspec - > path ) ;
2014-08-21 16:19:25 +02:00
2013-11-19 21:12:59 +01:00
r = path_spec_watch ( s - > pid_file_pathspec , service_dispatch_io ) ;
2011-12-03 02:13:30 +01:00
if ( r < 0 )
goto fail ;
/* the pidfile might have appeared just before we set the watch */
2014-11-27 20:20:23 +01:00
log_unit_debug ( UNIT ( s ) - > id , " Trying to read %s's PID file %s in case it changed " , UNIT ( s ) - > id , s - > pid_file_pathspec - > path ) ;
2011-12-03 02:13:30 +01:00
service_retry_pid_file ( s ) ;
return 0 ;
fail :
2014-11-28 13:17:02 +01:00
log_unit_error_errno ( UNIT ( s ) - > id , r , " Failed to set a watch for %s's PID file %s: %m " , UNIT ( s ) - > id , s - > pid_file_pathspec - > path ) ;
2011-12-03 02:13:30 +01:00
service_unwatch_pid_file ( s ) ;
return r ;
}
static int service_demand_pid_file ( Service * s ) {
PathSpec * ps ;
assert ( s - > pid_file ) ;
assert ( ! s - > pid_file_pathspec ) ;
ps = new0 ( PathSpec , 1 ) ;
if ( ! ps )
return - ENOMEM ;
2013-11-19 21:12:59 +01:00
ps - > unit = UNIT ( s ) ;
2011-12-03 02:13:30 +01:00
ps - > path = strdup ( s - > pid_file ) ;
if ( ! ps - > path ) {
free ( ps ) ;
return - ENOMEM ;
}
path_kill_slashes ( ps - > path ) ;
/* PATH_CHANGED would not be enough. There are daemons (sendmail) that
* keep their PID file open all the time . */
ps - > type = PATH_MODIFIED ;
ps - > inotify_fd = - 1 ;
s - > pid_file_pathspec = ps ;
return service_watch_pid_file ( s ) ;
}
2013-11-19 21:12:59 +01:00
static int service_dispatch_io ( sd_event_source * source , int fd , uint32_t events , void * userdata ) {
2013-11-25 22:20:57 +01:00
PathSpec * p = userdata ;
Service * s ;
assert ( p ) ;
s = SERVICE ( p - > unit ) ;
2011-12-03 02:13:30 +01:00
assert ( s ) ;
assert ( fd > = 0 ) ;
assert ( s - > state = = SERVICE_START | | s - > state = = SERVICE_START_POST ) ;
assert ( s - > pid_file_pathspec ) ;
2012-01-06 23:08:54 +01:00
assert ( path_spec_owns_inotify_fd ( s - > pid_file_pathspec , fd ) ) ;
2011-12-03 02:13:30 +01:00
2014-11-27 20:20:23 +01:00
log_unit_debug ( UNIT ( s ) - > id , " inotify event for %s " , UNIT ( s ) - > id ) ;
2011-12-03 02:13:30 +01:00
2013-11-25 22:20:57 +01:00
if ( path_spec_fd_event ( p , events ) < 0 )
2011-12-03 02:13:30 +01:00
goto fail ;
if ( service_retry_pid_file ( s ) = = 0 )
2013-11-19 21:12:59 +01:00
return 0 ;
2011-12-03 02:13:30 +01:00
if ( service_watch_pid_file ( s ) < 0 )
goto fail ;
2013-11-19 21:12:59 +01:00
return 0 ;
2011-12-03 02:13:30 +01:00
fail :
service_unwatch_pid_file ( s ) ;
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_STOP_SIGTERM , SERVICE_FAILURE_RESOURCES ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
2011-12-03 02:13:30 +01:00
}
2014-02-06 17:17:51 +01:00
static void service_notify_cgroup_empty_event ( Unit * u ) {
Service * s = SERVICE ( u ) ;
assert ( u ) ;
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s: cgroup is empty " , u - > id ) ;
2014-02-06 17:17:51 +01:00
switch ( s - > state ) {
/* Waiting for SIGCHLD is usually more interesting,
* because it includes return codes / signals . Which is
* why we ignore the cgroup events for most cases ,
* except when we don ' t know pid which to expect the
* SIGCHLD for . */
case SERVICE_START :
case SERVICE_START_POST :
/* If we were hoping for the daemon to write its PID file,
* we can give up now . */
if ( s - > pid_file_pathspec ) {
2014-11-27 20:20:23 +01:00
log_unit_warning ( u - > id , " %s never wrote its PID file. Failing. " , UNIT ( s ) - > id ) ;
2014-08-21 16:19:25 +02:00
2014-02-06 17:17:51 +01:00
service_unwatch_pid_file ( s ) ;
if ( s - > state = = SERVICE_START )
service_enter_signal ( s , SERVICE_FINAL_SIGTERM , SERVICE_FAILURE_RESOURCES ) ;
else
service_enter_stop ( s , SERVICE_FAILURE_RESOURCES ) ;
}
break ;
case SERVICE_RUNNING :
/* service_enter_running() will figure out what to do */
service_enter_running ( s , SERVICE_SUCCESS ) ;
break ;
2014-10-28 16:35:40 +01:00
case SERVICE_STOP_SIGABRT :
2014-02-06 17:17:51 +01:00
case SERVICE_STOP_SIGTERM :
case SERVICE_STOP_SIGKILL :
if ( main_pid_good ( s ) < = 0 & & ! control_pid_good ( s ) )
service_enter_stop_post ( s , SERVICE_SUCCESS ) ;
break ;
case SERVICE_STOP_POST :
case SERVICE_FINAL_SIGTERM :
case SERVICE_FINAL_SIGKILL :
if ( main_pid_good ( s ) < = 0 & & ! control_pid_good ( s ) )
service_enter_dead ( s , SERVICE_SUCCESS , true ) ;
break ;
default :
;
}
}
2010-01-26 21:39:06 +01:00
static void service_sigchld_event ( Unit * u , pid_t pid , int code , int status ) {
Service * s = SERVICE ( u ) ;
2012-02-03 02:01:35 +01:00
ServiceResult f ;
2010-01-23 01:52:57 +01:00
assert ( s ) ;
2010-01-26 04:18:44 +01:00
assert ( pid > = 0 ) ;
2012-08-13 13:58:01 +02:00
if ( UNIT ( s ) - > fragment_path ? is_clean_exit ( code , status , & s - > success_status ) :
is_clean_exit_lsb ( code , status , & s - > success_status ) )
2012-02-03 02:01:35 +01:00
f = SERVICE_SUCCESS ;
else if ( code = = CLD_EXITED )
f = SERVICE_FAILURE_EXIT_CODE ;
else if ( code = = CLD_KILLED )
f = SERVICE_FAILURE_SIGNAL ;
else if ( code = = CLD_DUMPED )
f = SERVICE_FAILURE_CORE_DUMP ;
2010-08-19 03:18:49 +02:00
else
2012-02-03 02:31:54 +01:00
assert_not_reached ( " Unknown code " ) ;
2010-01-26 04:18:44 +01:00
if ( s - > main_pid = = pid ) {
2011-09-20 21:43:30 +02:00
/* Forking services may occasionally move to a new PID.
* As long as they update the PID file before exiting the old
* PID , they ' re fine . */
2011-09-22 13:10:32 +02:00
if ( service_load_pid_file ( s , false ) = = 0 )
2011-09-20 21:43:30 +02:00
return ;
2010-01-26 04:18:44 +01:00
s - > main_pid = 0 ;
2011-05-18 01:07:31 +02:00
exec_status_exit ( & s - > main_exec_status , & s - > exec_context , pid , code , status ) ;
2010-01-26 04:18:44 +01:00
2011-01-20 18:46:38 +01:00
if ( s - > main_command ) {
2013-01-14 21:05:17 +01:00
/* If this is not a forking service than the
* main process got started and hence we copy
* the exit status so that it is recorded both
* as main and as control process exit
* status */
2011-01-20 18:46:38 +01:00
s - > main_command - > exec_status = s - > main_exec_status ;
2010-07-12 02:25:42 +02:00
2011-01-20 18:46:38 +01:00
if ( s - > main_command - > ignore )
2012-02-03 02:01:35 +01:00
f = SERVICE_SUCCESS ;
2013-01-14 21:05:17 +01:00
} else if ( s - > exec_command [ SERVICE_EXEC_START ] ) {
/* If this is a forked process, then we should
* ignore the return value if this was
* configured for the starter process */
if ( s - > exec_command [ SERVICE_EXEC_START ] - > ignore )
f = SERVICE_SUCCESS ;
2010-01-26 04:18:44 +01:00
}
2014-11-28 02:05:14 +01:00
log_unit_struct ( u - > id ,
f = = SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE ,
LOG_MESSAGE ( " %s: main process exited, code=%s, status=%i/%s " ,
u - > id , sigchld_code_to_string ( code ) , status ,
strna ( code = = CLD_EXITED
? exit_status_to_string ( status , EXIT_STATUS_FULL )
: signal_to_string ( status ) ) ) ,
" EXIT_CODE=%s " , sigchld_code_to_string ( code ) ,
" EXIT_STATUS=%i " , status ,
NULL ) ;
2012-02-03 02:01:35 +01:00
if ( f ! = SERVICE_SUCCESS )
s - > result = f ;
2010-01-26 04:18:44 +01:00
2011-01-20 18:46:38 +01:00
if ( s - > main_command & &
s - > main_command - > command_next & &
2012-02-03 02:01:35 +01:00
f = = SERVICE_SUCCESS ) {
2010-01-26 04:18:44 +01:00
2010-08-13 18:23:01 +02:00
/* There is another command to *
* execute , so let ' s do that . */
2010-01-26 04:18:44 +01:00
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s running next main command for state %s " , u - > id , service_state_to_string ( s - > state ) ) ;
2012-02-03 02:01:35 +01:00
service_run_next_main ( s ) ;
2010-01-26 04:18:44 +01:00
2010-08-13 18:23:01 +02:00
} else {
/* The service exited, so the service is officially
* gone . */
2011-01-20 18:46:38 +01:00
s - > main_command = NULL ;
2010-08-13 18:23:01 +02:00
switch ( s - > state ) {
case SERVICE_START_POST :
case SERVICE_RELOAD :
case SERVICE_STOP :
/* Need to wait until the operation is
* done */
2010-06-04 21:23:00 +02:00
break ;
2010-01-30 02:07:35 +01:00
2010-08-13 18:23:01 +02:00
case SERVICE_START :
if ( s - > type = = SERVICE_ONESHOT ) {
/* This was our main goal, so let's go on */
2012-02-03 02:01:35 +01:00
if ( f = = SERVICE_SUCCESS )
2010-08-13 18:23:01 +02:00
service_enter_start_post ( s ) ;
else
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_FINAL_SIGTERM , f ) ;
2010-08-13 18:23:01 +02:00
break ;
}
2010-01-26 04:18:44 +01:00
2012-09-17 14:55:56 +02:00
/* Fall through */
2010-08-13 18:23:01 +02:00
case SERVICE_RUNNING :
2012-02-03 02:01:35 +01:00
service_enter_running ( s , f ) ;
2010-08-13 18:23:01 +02:00
break ;
2010-01-26 04:18:44 +01:00
2014-10-28 16:35:40 +01:00
case SERVICE_STOP_SIGABRT :
2010-08-13 18:23:01 +02:00
case SERVICE_STOP_SIGTERM :
case SERVICE_STOP_SIGKILL :
2010-01-23 01:52:57 +01:00
2010-08-13 18:23:01 +02:00
if ( ! control_pid_good ( s ) )
2012-02-03 02:01:35 +01:00
service_enter_stop_post ( s , f ) ;
2010-01-23 01:52:57 +01:00
2010-08-13 18:23:01 +02:00
/* If there is still a control process, wait for that first */
break ;
2013-12-18 04:19:20 +01:00
case SERVICE_STOP_POST :
case SERVICE_FINAL_SIGTERM :
case SERVICE_FINAL_SIGKILL :
if ( ! control_pid_good ( s ) )
service_enter_dead ( s , f , true ) ;
break ;
2010-08-13 18:23:01 +02:00
default :
assert_not_reached ( " Uh, main process died at wrong time. " ) ;
}
2010-01-26 04:18:44 +01:00
}
2010-01-23 01:52:57 +01:00
2010-01-26 04:18:44 +01:00
} else if ( s - > control_pid = = pid ) {
2010-08-13 18:23:01 +02:00
s - > control_pid = 0 ;
2010-07-12 02:25:42 +02:00
if ( s - > control_command ) {
2014-08-21 16:19:25 +02:00
exec_status_exit ( & s - > control_command - > exec_status , & s - > exec_context , pid , code , status ) ;
2010-04-21 03:27:44 +02:00
2010-07-12 02:25:42 +02:00
if ( s - > control_command - > ignore )
2012-02-03 02:01:35 +01:00
f = SERVICE_SUCCESS ;
2010-07-12 02:25:42 +02:00
}
2014-11-27 20:20:23 +01:00
log_unit_full ( u - > id ,
f = = SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE ,
2013-01-05 18:00:35 +01:00
" %s: control process exited, code=%s status=%i " ,
u - > id , sigchld_code_to_string ( code ) , status ) ;
2012-02-03 02:01:35 +01:00
if ( f ! = SERVICE_SUCCESS )
s - > result = f ;
2010-01-26 04:18:44 +01:00
2012-05-03 21:54:44 +02:00
/* Immediately get rid of the cgroup, so that the
* kernel doesn ' t delay the cgroup empty messages for
* the service cgroup any longer than necessary */
2013-06-27 04:14:27 +02:00
service_kill_control_processes ( s ) ;
2012-05-03 21:54:44 +02:00
2010-08-13 18:23:01 +02:00
if ( s - > control_command & &
s - > control_command - > command_next & &
2012-02-03 02:01:35 +01:00
f = = SERVICE_SUCCESS ) {
2010-01-26 04:18:44 +01:00
/* There is another command to *
* execute , so let ' s do that . */
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s running next control command for state %s " , u - > id , service_state_to_string ( s - > state ) ) ;
2012-02-03 02:01:35 +01:00
service_run_next_control ( s ) ;
2010-01-26 04:18:44 +01:00
2010-04-13 02:06:27 +02:00
} else {
2010-01-26 04:18:44 +01:00
/* No further commands for this step, so let's
* figure out what to do next */
2010-04-21 03:27:44 +02:00
s - > control_command = NULL ;
s - > control_command_id = _SERVICE_EXEC_COMMAND_INVALID ;
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s got final SIGCHLD for state %s " , u - > id , service_state_to_string ( s - > state ) ) ;
2010-01-27 05:32:31 +01:00
2010-01-26 04:18:44 +01:00
switch ( s - > state ) {
case SERVICE_START_PRE :
2012-02-03 02:01:35 +01:00
if ( f = = SERVICE_SUCCESS )
2010-01-26 04:18:44 +01:00
service_enter_start ( s ) ;
else
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_FINAL_SIGTERM , f ) ;
2010-01-26 04:18:44 +01:00
break ;
case SERVICE_START :
2012-09-17 14:55:56 +02:00
if ( s - > type ! = SERVICE_FORKING )
/* Maybe spurious event due to a reload that changed the type? */
break ;
2010-01-26 04:18:44 +01:00
2012-02-03 02:01:35 +01:00
if ( f ! = SERVICE_SUCCESS ) {
service_enter_signal ( s , SERVICE_FINAL_SIGTERM , f ) ;
2011-12-03 02:13:30 +01:00
break ;
}
2010-01-26 04:18:44 +01:00
2011-12-03 02:13:30 +01:00
if ( s - > pid_file ) {
2012-02-03 02:01:35 +01:00
bool has_start_post ;
int r ;
2011-12-03 02:13:30 +01:00
/* Let's try to load the pid file here if we can.
* The PID file might actually be created by a START_POST
* script . In that case don ' t worry if the loading fails . */
2012-02-03 02:01:35 +01:00
has_start_post = ! ! s - > exec_command [ SERVICE_EXEC_START_POST ] ;
r = service_load_pid_file ( s , ! has_start_post ) ;
2011-12-03 02:13:30 +01:00
if ( ! has_start_post & & r < 0 ) {
r = service_demand_pid_file ( s ) ;
if ( r < 0 | | ! cgroup_good ( s ) )
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_FINAL_SIGTERM , SERVICE_FAILURE_RESOURCES ) ;
2011-12-03 02:13:30 +01:00
break ;
}
2010-01-26 04:18:44 +01:00
} else
2011-12-03 02:13:30 +01:00
service_search_main_pid ( s ) ;
2010-01-26 04:18:44 +01:00
2011-12-03 02:13:30 +01:00
service_enter_start_post ( s ) ;
2010-01-26 04:18:44 +01:00
break ;
case SERVICE_START_POST :
2012-02-03 02:01:35 +01:00
if ( f ! = SERVICE_SUCCESS ) {
service_enter_stop ( s , f ) ;
2011-12-03 21:34:34 +01:00
break ;
2010-01-26 04:18:44 +01:00
}
2011-12-03 21:34:34 +01:00
if ( s - > pid_file ) {
2012-02-03 02:01:35 +01:00
int r ;
r = service_load_pid_file ( s , true ) ;
2011-12-03 21:34:34 +01:00
if ( r < 0 ) {
r = service_demand_pid_file ( s ) ;
if ( r < 0 | | ! cgroup_good ( s ) )
2012-02-03 02:01:35 +01:00
service_enter_stop ( s , SERVICE_FAILURE_RESOURCES ) ;
2011-12-03 21:34:34 +01:00
break ;
}
} else
service_search_main_pid ( s ) ;
2012-02-03 02:01:35 +01:00
service_enter_running ( s , SERVICE_SUCCESS ) ;
2011-02-13 18:51:30 +01:00
break ;
2010-01-26 04:18:44 +01:00
case SERVICE_RELOAD :
2012-02-03 02:01:35 +01:00
if ( f = = SERVICE_SUCCESS ) {
2011-09-22 13:10:32 +02:00
service_load_pid_file ( s , true ) ;
2011-02-13 18:51:30 +01:00
service_search_main_pid ( s ) ;
}
2012-02-03 02:01:35 +01:00
s - > reload_result = f ;
service_enter_running ( s , SERVICE_SUCCESS ) ;
2010-01-26 04:18:44 +01:00
break ;
case SERVICE_STOP :
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_STOP_SIGTERM , f ) ;
2010-01-26 04:18:44 +01:00
break ;
2014-10-28 16:35:40 +01:00
case SERVICE_STOP_SIGABRT :
2010-01-26 04:18:44 +01:00
case SERVICE_STOP_SIGTERM :
case SERVICE_STOP_SIGKILL :
if ( main_pid_good ( s ) < = 0 )
2012-02-03 02:01:35 +01:00
service_enter_stop_post ( s , f ) ;
2010-01-26 04:18:44 +01:00
/* If there is still a service
* process around , wait until
* that one quit , too */
break ;
case SERVICE_STOP_POST :
case SERVICE_FINAL_SIGTERM :
case SERVICE_FINAL_SIGKILL :
2013-12-18 04:19:20 +01:00
if ( main_pid_good ( s ) < = 0 )
service_enter_dead ( s , f , true ) ;
2010-01-26 04:18:44 +01:00
break ;
default :
assert_not_reached ( " Uh, control process died at wrong time. " ) ;
}
}
2010-06-16 05:10:31 +02:00
}
2010-08-20 02:26:05 +02:00
/* Notify clients about changed exit status */
unit_add_to_dbus_queue ( u ) ;
2014-02-06 17:17:51 +01:00
/* We got one SIGCHLD for the service, let's watch all
* processes that are now running of the service , and watch
* that . Among the PIDs we then watch will be children
* reassigned to us , which hopefully allows us to identify
* when all children are gone */
unit_tidy_watch_pids ( u , s - > main_pid , s - > control_pid ) ;
unit_watch_all_pids ( u ) ;
/* If the PID set is empty now, then let's finish this off */
if ( set_isempty ( u - > pids ) )
service_notify_cgroup_empty_event ( u ) ;
2010-01-26 04:18:44 +01:00
}
2013-11-19 21:12:59 +01:00
static int service_dispatch_timer ( sd_event_source * source , usec_t usec , void * userdata ) {
Service * s = SERVICE ( userdata ) ;
2010-01-26 04:18:44 +01:00
assert ( s ) ;
2013-11-19 21:12:59 +01:00
assert ( source = = s - > timer_event_source ) ;
2010-01-26 04:18:44 +01:00
switch ( s - > state ) {
case SERVICE_START_PRE :
case SERVICE_START :
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s %s operation timed out. Terminating. " , UNIT ( s ) - > id , s - > state = = SERVICE_START ? " start " : " start-pre " ) ;
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_FINAL_SIGTERM , SERVICE_FAILURE_TIMEOUT ) ;
2010-04-13 02:06:27 +02:00
break ;
2010-01-26 04:18:44 +01:00
case SERVICE_START_POST :
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s start-post operation timed out. Stopping. " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_stop ( s , SERVICE_FAILURE_TIMEOUT ) ;
2010-01-26 04:18:44 +01:00
break ;
2011-01-20 13:17:22 +01:00
case SERVICE_RELOAD :
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s reload operation timed out. Stopping. " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
s - > reload_result = SERVICE_FAILURE_TIMEOUT ;
service_enter_running ( s , SERVICE_SUCCESS ) ;
2011-01-20 13:17:22 +01:00
break ;
2010-01-26 04:18:44 +01:00
case SERVICE_STOP :
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s stopping timed out. Terminating. " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_STOP_SIGTERM , SERVICE_FAILURE_TIMEOUT ) ;
2010-01-26 04:18:44 +01:00
break ;
2014-10-28 16:35:40 +01:00
case SERVICE_STOP_SIGABRT :
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id ,
2014-10-28 16:35:40 +01:00
" %s stop-sigabrt timed out. Terminating. " , UNIT ( s ) - > id ) ;
service_enter_signal ( s , SERVICE_STOP_SIGTERM , s - > result ) ;
break ;
2010-01-26 04:18:44 +01:00
case SERVICE_STOP_SIGTERM :
2012-07-19 23:47:10 +02:00
if ( s - > kill_context . send_sigkill ) {
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s stop-sigterm timed out. Killing. " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_STOP_SIGKILL , SERVICE_FAILURE_TIMEOUT ) ;
2011-01-18 22:55:54 +01:00
} else {
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s stop-sigterm timed out. Skipping SIGKILL. " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_stop_post ( s , SERVICE_FAILURE_TIMEOUT ) ;
2011-01-18 22:55:54 +01:00
}
2010-01-26 04:18:44 +01:00
break ;
case SERVICE_STOP_SIGKILL :
2011-02-21 15:32:17 +01:00
/* Uh, we sent a SIGKILL and it is still not gone?
2010-01-26 04:18:44 +01:00
* Must be something we cannot kill , so let ' s just be
* weirded out and continue */
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s still around after SIGKILL. Ignoring. " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_stop_post ( s , SERVICE_FAILURE_TIMEOUT ) ;
2010-01-26 04:18:44 +01:00
break ;
case SERVICE_STOP_POST :
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s stop-post timed out. Terminating. " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_FINAL_SIGTERM , SERVICE_FAILURE_TIMEOUT ) ;
2010-01-26 04:18:44 +01:00
break ;
case SERVICE_FINAL_SIGTERM :
2012-07-19 23:47:10 +02:00
if ( s - > kill_context . send_sigkill ) {
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s stop-final-sigterm timed out. Killing. " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_signal ( s , SERVICE_FINAL_SIGKILL , SERVICE_FAILURE_TIMEOUT ) ;
2011-01-18 22:55:54 +01:00
} else {
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s stop-final-sigterm timed out. Skipping SIGKILL. Entering failed mode. " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_dead ( s , SERVICE_FAILURE_TIMEOUT , false ) ;
2011-01-18 22:55:54 +01:00
}
2010-01-26 04:18:44 +01:00
break ;
case SERVICE_FINAL_SIGKILL :
2014-11-27 20:20:23 +01:00
log_unit_warning ( UNIT ( s ) - > id , " %s still around after final SIGKILL. Entering failed mode. " , UNIT ( s ) - > id ) ;
2012-02-03 02:01:35 +01:00
service_enter_dead ( s , SERVICE_FAILURE_TIMEOUT , true ) ;
2010-01-26 04:18:44 +01:00
break ;
case SERVICE_AUTO_RESTART :
2014-11-27 20:20:23 +01:00
log_unit_info ( UNIT ( s ) - > id ,
2014-02-13 23:10:12 +01:00
s - > restart_usec > 0 ?
" %s holdoff time over, scheduling restart. " :
" %s has no holdoff time, scheduling restart. " ,
UNIT ( s ) - > id ) ;
2010-01-26 04:18:44 +01:00
service_enter_restart ( s ) ;
break ;
default :
assert_not_reached ( " Timeout at wrong time. " ) ;
}
2013-11-19 21:12:59 +01:00
return 0 ;
}
static int service_dispatch_watchdog ( sd_event_source * source , usec_t usec , void * userdata ) {
Service * s = SERVICE ( userdata ) ;
2013-12-27 23:14:24 +01:00
char t [ FORMAT_TIMESPAN_MAX ] ;
2013-11-19 21:12:59 +01:00
assert ( s ) ;
assert ( source = = s - > watchdog_event_source ) ;
2014-11-27 20:20:23 +01:00
log_unit_error ( UNIT ( s ) - > id , " %s watchdog timeout (limit %s)! " , UNIT ( s ) - > id ,
2013-12-27 23:14:24 +01:00
format_timespan ( t , sizeof ( t ) , s - > watchdog_usec , 1 ) ) ;
2014-08-21 16:19:25 +02:00
2014-10-28 16:35:40 +01:00
service_enter_signal ( s , SERVICE_STOP_SIGABRT , SERVICE_FAILURE_WATCHDOG ) ;
2013-12-11 20:49:43 +01:00
2013-11-19 21:12:59 +01:00
return 0 ;
2010-01-23 01:52:57 +01:00
}
2015-01-06 00:26:25 +01:00
static void service_notify_message ( Unit * u , pid_t pid , char * * tags , FDSet * fds ) {
2010-06-16 05:10:31 +02:00
Service * s = SERVICE ( u ) ;
2014-08-21 17:03:15 +02:00
_cleanup_free_ char * cc = NULL ;
2013-12-19 21:34:09 +01:00
bool notify_dbus = false ;
2014-08-21 17:03:15 +02:00
const char * e ;
2010-06-16 05:10:31 +02:00
assert ( u ) ;
2014-08-21 17:03:15 +02:00
cc = strv_join ( tags , " , " ) ;
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s: Got notification message from PID " PID_FMT " (%s) " ,
2014-08-21 17:03:15 +02:00
u - > id , pid , isempty ( cc ) ? " n/a " : cc ) ;
2013-12-30 17:21:56 +01:00
2010-06-18 23:12:48 +02:00
if ( s - > notify_access = = NOTIFY_NONE ) {
2014-11-27 20:20:23 +01:00
log_unit_warning ( u - > id , " %s: Got notification message from PID " PID_FMT " , but reception is disabled. " , u - > id , pid ) ;
2010-06-18 23:12:48 +02:00
return ;
}
2014-02-14 02:04:09 +01:00
if ( s - > notify_access = = NOTIFY_MAIN & & pid ! = s - > main_pid ) {
if ( s - > main_pid ! = 0 )
2014-11-27 20:20:23 +01:00
log_unit_warning ( u - > id , " %s: Got notification message from PID " PID_FMT " , but reception only permitted for main PID " PID_FMT , u - > id , pid , s - > main_pid ) ;
2014-02-14 02:04:09 +01:00
else
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s: Got notification message from PID " PID_FMT " , but reception only permitted for main PID which is currently not known " , u - > id , pid ) ;
2010-06-18 23:12:48 +02:00
return ;
}
2010-06-16 05:10:31 +02:00
/* Interpret MAINPID= */
2014-08-21 16:22:34 +02:00
e = strv_find_startswith ( tags , " MAINPID= " ) ;
2014-07-07 17:03:34 +02:00
if ( e & & IN_SET ( s - > state , SERVICE_START , SERVICE_START_POST , SERVICE_RUNNING , SERVICE_RELOAD ) ) {
2014-08-21 16:22:34 +02:00
if ( parse_pid ( e , & pid ) < 0 )
2014-11-27 20:20:23 +01:00
log_unit_warning ( u - > id , " Failed to parse MAINPID= field in notification message: %s " , e ) ;
2010-06-16 05:10:31 +02:00
else {
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s: got MAINPID=%s " , u - > id , e ) ;
2014-08-21 16:22:34 +02:00
2010-06-17 22:55:53 +02:00
service_set_main_pid ( s , pid ) ;
2013-10-01 05:06:56 +02:00
unit_watch_pid ( UNIT ( s ) , pid ) ;
2013-12-19 21:34:09 +01:00
notify_dbus = true ;
2010-06-16 05:10:31 +02:00
}
}
2014-08-21 17:03:15 +02:00
/* Interpret RELOADING= */
if ( strv_find ( tags , " RELOADING=1 " ) ) {
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s: got RELOADING=1 " , u - > id ) ;
2014-08-21 17:03:15 +02:00
s - > notify_state = NOTIFY_RELOADING ;
if ( s - > state = = SERVICE_RUNNING )
service_enter_reload_by_notify ( s ) ;
notify_dbus = true ;
}
2010-06-16 05:10:31 +02:00
/* Interpret READY= */
2014-08-21 17:03:15 +02:00
if ( strv_find ( tags , " READY=1 " ) ) {
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s: got READY=1 " , u - > id ) ;
2014-08-21 17:03:15 +02:00
s - > notify_state = NOTIFY_READY ;
/* Type=notify services inform us about completed
* initialization with READY = 1 */
if ( s - > type = = SERVICE_NOTIFY & & s - > state = = SERVICE_START )
service_enter_start_post ( s ) ;
/* Sending READY=1 while we are reloading informs us
* that the reloading is complete */
if ( s - > state = = SERVICE_RELOAD & & s - > control_pid = = 0 )
service_enter_running ( s , SERVICE_SUCCESS ) ;
notify_dbus = true ;
}
/* Interpret STOPPING= */
if ( strv_find ( tags , " STOPPING=1 " ) ) {
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s: got STOPPING=1 " , u - > id ) ;
2014-08-21 17:03:15 +02:00
s - > notify_state = NOTIFY_STOPPING ;
if ( s - > state = = SERVICE_RUNNING )
service_enter_stop_by_notify ( s ) ;
2013-12-19 21:34:09 +01:00
notify_dbus = true ;
2010-06-16 05:10:31 +02:00
}
/* Interpret STATUS= */
2014-08-21 16:22:34 +02:00
e = strv_find_startswith ( tags , " STATUS= " ) ;
2012-03-12 22:22:16 +01:00
if ( e ) {
2014-08-21 16:22:34 +02:00
_cleanup_free_ char * t = NULL ;
2010-06-16 05:10:31 +02:00
2014-08-21 16:22:34 +02:00
if ( ! isempty ( e ) ) {
if ( ! utf8_is_valid ( e ) )
2014-11-27 20:20:23 +01:00
log_unit_warning ( u - > id , " Status message in notification is not UTF-8 clean. " ) ;
2014-08-21 16:22:34 +02:00
else {
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s: got STATUS=%s " , u - > id , e ) ;
2012-03-12 22:22:16 +01:00
2014-08-21 16:22:34 +02:00
t = strdup ( e ) ;
if ( ! t )
log_oom ( ) ;
2010-07-21 05:16:45 +02:00
}
2014-08-21 16:22:34 +02:00
}
2010-06-16 05:10:31 +02:00
2013-12-19 21:34:09 +01:00
if ( ! streq_ptr ( s - > status_text , t ) ) {
2014-08-21 16:22:34 +02:00
2010-07-21 05:16:45 +02:00
free ( s - > status_text ) ;
s - > status_text = t ;
2014-08-21 16:22:34 +02:00
t = NULL ;
2013-12-19 21:34:09 +01:00
notify_dbus = true ;
2014-08-21 16:22:34 +02:00
}
2010-06-16 05:10:31 +02:00
}
2013-12-11 20:49:43 +01:00
2014-07-07 14:20:36 +02:00
/* Interpret ERRNO= */
2014-08-21 16:22:34 +02:00
e = strv_find_startswith ( tags , " ERRNO= " ) ;
2014-07-07 14:20:36 +02:00
if ( e ) {
int status_errno ;
2014-08-21 16:22:34 +02:00
if ( safe_atoi ( e , & status_errno ) < 0 | | status_errno < 0 )
2014-11-27 20:20:23 +01:00
log_unit_warning ( u - > id , " Failed to parse ERRNO= field in notification message: %s " , e ) ;
2014-07-07 14:20:36 +02:00
else {
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s: got ERRNO=%s " , u - > id , e ) ;
2014-07-07 14:20:36 +02:00
if ( s - > status_errno ! = status_errno ) {
s - > status_errno = status_errno ;
notify_dbus = true ;
}
}
}
2014-03-14 21:13:38 +01:00
/* Interpret WATCHDOG= */
2012-02-01 17:17:12 +01:00
if ( strv_find ( tags , " WATCHDOG=1 " ) ) {
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s: got WATCHDOG=1 " , u - > id ) ;
2013-12-11 20:49:43 +01:00
service_reset_watchdog ( s ) ;
2012-02-01 17:17:12 +01:00
}
2010-08-20 02:26:05 +02:00
2015-01-06 00:26:25 +01:00
/* Add the passed fds to the fd store */
if ( strv_find ( tags , " FDSTORE=1 " ) ) {
log_unit_debug ( u - > id , " %s: got FDSTORE=1 " , u - > id ) ;
2015-01-07 01:18:13 +01:00
service_add_fd_store_set ( s , fds ) ;
2015-01-06 00:26:25 +01:00
}
2010-08-20 02:26:05 +02:00
/* Notify clients about changed status or main pid */
2013-12-19 21:34:09 +01:00
if ( notify_dbus )
unit_add_to_dbus_queue ( u ) ;
2010-06-16 05:10:31 +02:00
}
2014-01-27 06:57:34 +01:00
static int service_get_timeout ( Unit * u , uint64_t * timeout ) {
Service * s = SERVICE ( u ) ;
int r ;
if ( ! s - > timer_event_source )
return 0 ;
r = sd_event_source_get_time ( s - > timer_event_source , timeout ) ;
if ( r < 0 )
return r ;
return 1 ;
}
2010-04-15 23:16:16 +02:00
static void service_bus_name_owner_change (
Unit * u ,
const char * name ,
const char * old_owner ,
const char * new_owner ) {
Service * s = SERVICE ( u ) ;
2013-11-19 21:12:59 +01:00
int r ;
2010-04-15 23:16:16 +02:00
assert ( s ) ;
assert ( name ) ;
assert ( streq ( s - > bus_name , name ) ) ;
assert ( old_owner | | new_owner ) ;
if ( old_owner & & new_owner )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s's D-Bus name %s changed owner from %s to %s " , u - > id , name , old_owner , new_owner ) ;
2010-04-15 23:16:16 +02:00
else if ( old_owner )
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s's D-Bus name %s no longer registered by %s " , u - > id , name , old_owner ) ;
2010-04-15 23:16:16 +02:00
else
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s's D-Bus name %s now registered by %s " , u - > id , name , new_owner ) ;
2010-04-15 23:16:16 +02:00
s - > bus_name_good = ! ! new_owner ;
if ( s - > type = = SERVICE_DBUS ) {
/* service_enter_running() will figure out what to
* do */
if ( s - > state = = SERVICE_RUNNING )
2012-02-03 02:01:35 +01:00
service_enter_running ( s , SERVICE_SUCCESS ) ;
2010-04-15 23:16:16 +02:00
else if ( s - > state = = SERVICE_START & & new_owner )
service_enter_start_post ( s ) ;
} else if ( new_owner & &
s - > main_pid < = 0 & &
( s - > state = = SERVICE_START | |
s - > state = = SERVICE_START_POST | |
s - > state = = SERVICE_RUNNING | |
s - > state = = SERVICE_RELOAD ) ) {
2013-11-28 17:50:02 +01:00
_cleanup_bus_creds_unref_ sd_bus_creds * creds = NULL ;
2013-11-19 21:12:59 +01:00
pid_t pid ;
2010-04-15 23:16:16 +02:00
2013-11-19 21:12:59 +01:00
/* Try to acquire PID from bus service */
2010-04-15 23:16:16 +02:00
2014-10-22 19:17:24 +02:00
r = sd_bus_get_name_creds ( u - > manager - > api_bus , name , SD_BUS_CREDS_PID , & creds ) ;
2013-11-28 17:50:02 +01:00
if ( r > = 0 )
r = sd_bus_creds_get_pid ( creds , & pid ) ;
2013-11-19 21:12:59 +01:00
if ( r > = 0 ) {
2014-11-27 20:20:23 +01:00
log_unit_debug ( u - > id , " %s's D-Bus name %s is now owned by process %u " , u - > id , name , ( unsigned ) pid ) ;
2010-04-15 23:16:16 +02:00
2013-11-19 21:12:59 +01:00
service_set_main_pid ( s , pid ) ;
unit_watch_pid ( UNIT ( s ) , pid ) ;
}
2013-10-01 05:06:56 +02:00
}
2010-04-15 23:16:16 +02:00
}
2014-07-24 10:40:28 +02:00
int service_set_socket_fd ( Service * s , int fd , Socket * sock , bool selinux_context_net ) {
2013-12-24 21:18:21 +01:00
_cleanup_free_ char * peer = NULL ;
int r ;
2012-01-06 23:08:54 +01:00
2010-04-15 06:19:54 +02:00
assert ( s ) ;
assert ( fd > = 0 ) ;
/* This is called by the socket code when instantiating a new
* service for a stream socket and the socket needs to be
* configured . */
2012-01-15 12:25:20 +01:00
if ( UNIT ( s ) - > load_state ! = UNIT_LOADED )
2010-04-15 06:19:54 +02:00
return - EINVAL ;
if ( s - > socket_fd > = 0 )
return - EBUSY ;
if ( s - > state ! = SERVICE_DEAD )
return - EAGAIN ;
2013-12-24 21:18:21 +01:00
if ( getpeername_pretty ( fd , & peer ) > = 0 ) {
if ( UNIT ( s ) - > description ) {
_cleanup_free_ char * a ;
a = strjoin ( UNIT ( s ) - > description , " ( " , peer , " ) " , NULL ) ;
if ( ! a )
return - ENOMEM ;
r = unit_set_description ( UNIT ( s ) , a ) ;
} else
r = unit_set_description ( UNIT ( s ) , peer ) ;
if ( r < 0 )
return r ;
}
2010-04-15 06:19:54 +02:00
s - > socket_fd = fd ;
2014-07-24 10:40:28 +02:00
s - > socket_fd_selinux_context_net = selinux_context_net ;
2010-06-19 04:25:28 +02:00
2012-01-06 23:08:54 +01:00
unit_ref_set ( & s - > accept_socket , UNIT ( sock ) ) ;
return unit_add_two_dependencies ( UNIT ( sock ) , UNIT_BEFORE , UNIT_TRIGGERS , UNIT ( s ) , false ) ;
2010-04-15 06:19:54 +02:00
}
2010-08-31 00:23:34 +02:00
static void service_reset_failed ( Unit * u ) {
2010-07-18 04:58:01 +02:00
Service * s = SERVICE ( u ) ;
assert ( s ) ;
2010-08-31 00:23:34 +02:00
if ( s - > state = = SERVICE_FAILED )
2010-07-18 04:58:01 +02:00
service_set_state ( s , SERVICE_DEAD ) ;
2012-02-03 02:01:35 +01:00
s - > result = SERVICE_SUCCESS ;
s - > reload_result = SERVICE_SUCCESS ;
2012-07-04 00:23:42 +02:00
RATELIMIT_RESET ( s - > start_limit ) ;
2010-07-18 04:58:01 +02:00
}
2013-11-19 21:12:59 +01:00
static int service_kill ( Unit * u , KillWho who , int signo , sd_bus_error * error ) {
2010-10-22 16:11:50 +02:00
Service * s = SERVICE ( u ) ;
2013-08-09 16:40:57 +02:00
2013-03-02 22:31:09 +01:00
return unit_kill_common ( u , who , signo , s - > main_pid , s - > control_pid , error ) ;
2010-10-22 16:11:50 +02:00
}
2010-01-30 01:55:42 +01:00
static const char * const service_state_table [ _SERVICE_STATE_MAX ] = {
[ SERVICE_DEAD ] = " dead " ,
[ SERVICE_START_PRE ] = " start-pre " ,
[ SERVICE_START ] = " start " ,
[ SERVICE_START_POST ] = " start-post " ,
[ SERVICE_RUNNING ] = " running " ,
2010-04-13 02:06:27 +02:00
[ SERVICE_EXITED ] = " exited " ,
2010-01-30 01:55:42 +01:00
[ SERVICE_RELOAD ] = " reload " ,
[ SERVICE_STOP ] = " stop " ,
2014-10-28 18:06:58 +01:00
[ SERVICE_STOP_SIGABRT ] = " stop-sigabrt " ,
2010-01-30 01:55:42 +01:00
[ SERVICE_STOP_SIGTERM ] = " stop-sigterm " ,
[ SERVICE_STOP_SIGKILL ] = " stop-sigkill " ,
[ SERVICE_STOP_POST ] = " stop-post " ,
[ SERVICE_FINAL_SIGTERM ] = " final-sigterm " ,
[ SERVICE_FINAL_SIGKILL ] = " final-sigkill " ,
2010-08-31 00:23:34 +02:00
[ SERVICE_FAILED ] = " failed " ,
2010-01-30 01:55:42 +01:00
[ SERVICE_AUTO_RESTART ] = " auto-restart " ,
} ;
DEFINE_STRING_TABLE_LOOKUP ( service_state , ServiceState ) ;
static const char * const service_restart_table [ _SERVICE_RESTART_MAX ] = {
2010-10-05 20:30:44 +02:00
[ SERVICE_RESTART_NO ] = " no " ,
[ SERVICE_RESTART_ON_SUCCESS ] = " on-success " ,
2010-10-08 18:34:54 +02:00
[ SERVICE_RESTART_ON_FAILURE ] = " on-failure " ,
2014-06-05 18:42:52 +02:00
[ SERVICE_RESTART_ON_ABNORMAL ] = " on-abnormal " ,
2013-07-25 14:07:59 +02:00
[ SERVICE_RESTART_ON_WATCHDOG ] = " on-watchdog " ,
2010-10-08 18:34:54 +02:00
[ SERVICE_RESTART_ON_ABORT ] = " on-abort " ,
2014-06-05 18:42:52 +02:00
[ SERVICE_RESTART_ALWAYS ] = " always " ,
2010-01-30 01:55:42 +01:00
} ;
DEFINE_STRING_TABLE_LOOKUP ( service_restart , ServiceRestart ) ;
static const char * const service_type_table [ _SERVICE_TYPE_MAX ] = {
[ SERVICE_SIMPLE ] = " simple " ,
2010-07-01 19:39:35 +02:00
[ SERVICE_FORKING ] = " forking " ,
2010-08-13 18:23:01 +02:00
[ SERVICE_ONESHOT ] = " oneshot " ,
2010-06-16 05:10:31 +02:00
[ SERVICE_DBUS ] = " dbus " ,
2012-04-24 14:28:00 +02:00
[ SERVICE_NOTIFY ] = " notify " ,
[ SERVICE_IDLE ] = " idle "
2010-01-30 01:55:42 +01:00
} ;
DEFINE_STRING_TABLE_LOOKUP ( service_type , ServiceType ) ;
2010-04-10 17:53:17 +02:00
static const char * const service_exec_command_table [ _SERVICE_EXEC_COMMAND_MAX ] = {
2010-01-30 01:55:42 +01:00
[ SERVICE_EXEC_START_PRE ] = " ExecStartPre " ,
[ SERVICE_EXEC_START ] = " ExecStart " ,
[ SERVICE_EXEC_START_POST ] = " ExecStartPost " ,
[ SERVICE_EXEC_RELOAD ] = " ExecReload " ,
[ SERVICE_EXEC_STOP ] = " ExecStop " ,
[ SERVICE_EXEC_STOP_POST ] = " ExecStopPost " ,
} ;
DEFINE_STRING_TABLE_LOOKUP ( service_exec_command , ServiceExecCommand ) ;
2010-06-18 23:12:48 +02:00
static const char * const notify_access_table [ _NOTIFY_ACCESS_MAX ] = {
[ NOTIFY_NONE ] = " none " ,
[ NOTIFY_MAIN ] = " main " ,
[ NOTIFY_ALL ] = " all "
} ;
DEFINE_STRING_TABLE_LOOKUP ( notify_access , NotifyAccess ) ;
2014-08-21 17:03:15 +02:00
static const char * const notify_state_table [ _NOTIFY_STATE_MAX ] = {
[ NOTIFY_UNKNOWN ] = " unknown " ,
[ NOTIFY_READY ] = " ready " ,
[ NOTIFY_RELOADING ] = " reloading " ,
[ NOTIFY_STOPPING ] = " stopping " ,
} ;
DEFINE_STRING_TABLE_LOOKUP ( notify_state , NotifyState ) ;
2012-02-03 02:01:35 +01:00
static const char * const service_result_table [ _SERVICE_RESULT_MAX ] = {
[ SERVICE_SUCCESS ] = " success " ,
[ SERVICE_FAILURE_RESOURCES ] = " resources " ,
[ SERVICE_FAILURE_TIMEOUT ] = " timeout " ,
[ SERVICE_FAILURE_EXIT_CODE ] = " exit-code " ,
[ SERVICE_FAILURE_SIGNAL ] = " signal " ,
2012-02-08 10:10:34 +01:00
[ SERVICE_FAILURE_CORE_DUMP ] = " core-dump " ,
2012-08-22 05:02:33 +02:00
[ SERVICE_FAILURE_WATCHDOG ] = " watchdog " ,
[ SERVICE_FAILURE_START_LIMIT ] = " start-limit "
2012-02-03 02:01:35 +01:00
} ;
DEFINE_STRING_TABLE_LOOKUP ( service_result , ServiceResult ) ;
2010-01-26 21:39:06 +01:00
const UnitVTable service_vtable = {
2012-01-15 10:53:49 +01:00
. object_size = sizeof ( Service ) ,
2013-11-19 21:12:59 +01:00
. exec_context_offset = offsetof ( Service , exec_context ) ,
. cgroup_context_offset = offsetof ( Service , cgroup_context ) ,
. kill_context_offset = offsetof ( Service , kill_context ) ,
2013-11-27 20:23:18 +01:00
. exec_runtime_offset = offsetof ( Service , exec_runtime ) ,
2012-09-18 11:40:01 +02:00
2011-08-01 00:43:05 +02:00
. sections =
" Unit \0 "
" Service \0 "
" Install \0 " ,
2013-06-27 04:14:27 +02:00
. private_section = " Service " ,
2013-01-19 01:01:41 +01:00
2010-01-26 04:18:44 +01:00
. init = service_init ,
. done = service_done ,
2010-04-21 03:27:44 +02:00
. load = service_load ,
2015-01-06 00:26:25 +01:00
. release_resources = service_release_resources ,
2010-04-21 03:27:44 +02:00
. coldplug = service_coldplug ,
2010-01-26 04:18:44 +01:00
2010-01-23 01:52:57 +01:00
. dump = service_dump ,
. start = service_start ,
. stop = service_stop ,
. reload = service_reload ,
2010-01-26 04:18:44 +01:00
. can_reload = service_can_reload ,
2010-10-22 16:11:50 +02:00
. kill = service_kill ,
2010-04-21 03:27:44 +02:00
. serialize = service_serialize ,
. deserialize_item = service_deserialize_item ,
2010-01-23 01:52:57 +01:00
. active_state = service_active_state ,
2010-04-13 20:59:01 +02:00
. sub_state_to_string = service_sub_state_to_string ,
2010-01-23 01:52:57 +01:00
2010-04-21 06:01:13 +02:00
. check_gc = service_check_gc ,
. check_snapshot = service_check_snapshot ,
2010-01-26 04:18:44 +01:00
. sigchld_event = service_sigchld_event ,
2010-02-14 01:09:01 +01:00
2010-08-31 00:23:34 +02:00
. reset_failed = service_reset_failed ,
2010-07-18 04:58:01 +02:00
2013-06-27 04:14:27 +02:00
. notify_cgroup_empty = service_notify_cgroup_empty_event ,
2010-06-16 05:10:31 +02:00
. notify_message = service_notify_message ,
2010-03-31 16:29:55 +02:00
2010-04-15 23:16:16 +02:00
. bus_name_owner_change = service_bus_name_owner_change ,
2010-08-20 02:26:05 +02:00
. bus_interface = " org.freedesktop.systemd1.Service " ,
2013-11-19 21:12:59 +01:00
. bus_vtable = bus_service_vtable ,
2013-06-27 23:21:21 +02:00
. bus_set_property = bus_service_set_property ,
. bus_commit_properties = bus_service_commit_properties ,
2010-04-18 03:08:16 +02:00
2014-01-27 06:57:34 +01:00
. get_timeout = service_get_timeout ,
2013-11-19 21:12:59 +01:00
. can_transient = true ,
2012-05-13 18:18:54 +02:00
. status_message_formats = {
. starting_stopping = {
[ 0 ] = " Starting %s... " ,
[ 1 ] = " Stopping %s... " ,
} ,
. finished_start_job = {
[ JOB_DONE ] = " Started %s. " ,
[ JOB_FAILED ] = " Failed to start %s. " ,
[ JOB_DEPENDENCY ] = " Dependency failed for %s. " ,
[ JOB_TIMEOUT ] = " Timed out starting %s. " ,
} ,
. finished_stop_job = {
[ JOB_DONE ] = " Stopped %s. " ,
[ JOB_FAILED ] = " Stopped (with error) %s. " ,
[ JOB_TIMEOUT ] = " Timed out stopping %s. " ,
} ,
} ,
2010-01-23 01:52:57 +01:00
} ;