monitor.c revision 1bf580d3c6bbcfcff0c3dfd348e7c0a16d9d3d9e
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu Service monitor
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu Copyright (C) Simo Sorce 2008
431571057e88a650a974adec93ea4bb5173b6213Felix Gabriel Mance This program is free software; you can redistribute it and/or modify
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu it under the terms of the GNU General Public License as published by
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu the Free Software Foundation; either version 3 of the License, or
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu (at your option) any later version.
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu This program is distributed in the hope that it will be useful,
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu but WITHOUT ANY WARRANTY; without even the implied warranty of
19e01e1a7e319063434bd86c8ecbc5f241ef9993Felix Gabriel Mance MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu GNU General Public License for more details.
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu You should have received a copy of the GNU General Public License
a604cbad8e2202147b5c6bb9f2e06ae61162d654Felix Gabriel Mance along with this program. If not, see <http://www.gnu.org/licenses/>.
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu/* Needed for res_init() */
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu#include "monitor/monitor_interfaces.h"
b84c87f199dc287d235d7dad6ea344f6912ef531Christian Maeder#include "responder/common/responder_sbus.h"
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu/* ping time cannot be less then once every few seconds or the
27fdf879983dd28e211b41f3be6c0e930b7c816bFelix Gabriel Mance * monitor will get crazy hammering children with messages */
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu/* terminate the child after this interval by default if it
27fdf879983dd28e211b41f3be6c0e930b7c816bFelix Gabriel Mance * doesn't shutdown on receiving SIGTERM */
27fdf879983dd28e211b41f3be6c0e930b7c816bFelix Gabriel Mance/* TODO: get the restart related values from config */
d0f58d27c2536eba454d8f77de8617bc6a2c99cdFelix Gabriel Mance#define MONITOR_RESTART_CNT_INTERVAL_RESET 30
d0f58d27c2536eba454d8f77de8617bc6a2c99cdFelix Gabriel Mance/* maximum allowed number of service restarts if the restarts
d0f58d27c2536eba454d8f77de8617bc6a2c99cdFelix Gabriel Mance * were less than MONITOR_RESTART_CNT_INTERVAL_RESET apart, which would
d0f58d27c2536eba454d8f77de8617bc6a2c99cdFelix Gabriel Mance * indicate a crash after startup or after every request */
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu/* The services are restarted with a delay in case the restart was
27fdf879983dd28e211b41f3be6c0e930b7c816bFelix Gabriel Mance * hitting a race condition where the DP is not ready yet either.
424860079d47bf490fa98d5d7498096a0447c569mcodescu * The MONITOR_MAX_RESTART_DELAY defines the maximum delay between
424860079d47bf490fa98d5d7498096a0447c569mcodescu/* name of the monitor server instance */
60f30f0eeeacdfc1e0dfe39664373ddf5a0675adFelix Gabriel Mance#define SSSD_PIDFILE_PATH PID_PATH"/"MONITOR_NAME".pid"
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu/* Special value to leave the Kerberos Replay Cache set to use
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu * the libkrb5 defaults
60f30f0eeeacdfc1e0dfe39664373ddf5a0675adFelix Gabriel Mance#define KRB5_RCACHE_DIR_DISABLE "__LIBKRB5_DEFAULTS__"
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu struct config_file_callback *callbacks;
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu TALLOC_CTX *domain_ctx; /* Memory context for domain list */
32bbac77828be0233953f8fe476edb0a9585408dChristian Maeder TALLOC_CTX *service_ctx; /* Memory context for services */
cf0439f74f1d55a9840d38a88f9b0f4fc00d5547Christian Maederstatic int start_service(struct mt_svc *mt_svc);
cf0439f74f1d55a9840d38a88f9b0f4fc00d5547Christian Maederstatic int monitor_service_init(struct sbus_connection *conn, void *data);
cf0439f74f1d55a9840d38a88f9b0f4fc00d5547Christian Maederstatic int service_send_ping(struct mt_svc *svc);
cf0439f74f1d55a9840d38a88f9b0f4fc00d5547Christian Maederstatic int service_signal_reset_offline(struct mt_svc *svc);
cf0439f74f1d55a9840d38a88f9b0f4fc00d5547Christian Maederstatic void ping_check(DBusPendingCall *pending, void *data);
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiustatic void set_tasks_checker(struct mt_svc *srv);
7852de3551fc797566ee71165bafe05b6d81728cnotanartiststatic int monitor_kill_service (struct mt_svc *svc);
7852de3551fc797566ee71165bafe05b6d81728cnotanartiststatic int get_service_config(struct mt_ctx *ctx, const char *name,
624f8c31bd8d6746b93f4b5966aa6fc7680fefc5Felix Gabriel Mancestatic int get_provider_config(struct mt_ctx *ctx, const char *name,
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiustatic int add_new_service(struct mt_ctx *ctx,
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiustatic int add_new_provider(struct mt_ctx *ctx,
b84c87f199dc287d235d7dad6ea344f6912ef531Christian Maederstatic int mark_service_as_started(struct mt_svc *svc);
7852de3551fc797566ee71165bafe05b6d81728cnotanartiststatic int monitor_cleanup(void);
ee93ea764a2b8189253e912c8447f9419033f6d4Francisc Nicolae Bungiu struct mt_ctx *ctx = (struct mt_ctx *) cb_data;
431571057e88a650a974adec93ea4bb5173b6213Felix Gabriel Mance DEBUG(SSSDBG_TRACE_INTERNAL, ("A networking status change detected "
431571057e88a650a974adec93ea4bb5173b6213Felix Gabriel Mance "signaling providers to reset offline status\n"));
b90f0b7fd6ccfbdd7e5adb65b1f6c02c7758ff5cmcodescu for (iter = ctx->svc_list; iter; iter = iter->next) {
b90f0b7fd6ccfbdd7e5adb65b1f6c02c7758ff5cmcodescu /* Don't signal services, only providers */
b90f0b7fd6ccfbdd7e5adb65b1f6c02c7758ff5cmcodescu/* dbus_get_monitor_version
b90f0b7fd6ccfbdd7e5adb65b1f6c02c7758ff5cmcodescu * Return the monitor version over D-BUS */
b90f0b7fd6ccfbdd7e5adb65b1f6c02c7758ff5cmcodescustatic int get_monitor_version(DBusMessage *message,
return EIO;
return EOK;
struct mon_init_conn {
void *data;
char *svc_name;
int ret;
if (!mini) {
return EINVAL;
if (!dbret) {
goto done;
while (svc) {
if (ret == 0) {
if (!svc) {
goto done;
if (ret) {
goto done;
if (!dbret) {
return EIO;
done:
return EOK;
struct svc_spy {
if (!svc) {
if (!spy) {
return EOK;
int ret;
if (ret) {
goto done;
if (iter) {
goto done;
goto done;
errno = 0;
if (ret != 0) {
done:
return ret;
if (!to) {
return ENOMEM;
return EOK;
char *monitor_address;
int ret;
return ret;
return ret;
int ret;
switch (ret) {
case EOK:
case ENXIO:
int ret;
return ret;
int ret;
if (!reply) {
const char *filename)
int ret;
if(ret != 0) {
return EIO;
return EOK;
int ret;
return EOK;
return EIO;
if (!msg) {
return ENOMEM;
return ret;
while (dom) {
return EINVAL;
while (other) {
return EOK;
while (dom) {
count++;
return EINVAL;
return EOK;
char ***_services)
int ret;
char **domain_names;
size_t c;
char *conf_path;
char *id_provider;
bool add_pac = false;
return ENOMEM;
&domain_names);
goto done;
domain_names[c]);
goto done;
add_pac = true;
domain_names[c]));
goto done;
done:
return ret;
int ii;
for (i = 0; services[i]; i++) {
return services[i];
return NULL;
int ret;
int timeout_seconds;
return ret;
return ENOMEM;
return EINVAL;
return EINVAL;
return ENOMEM;
return ret;
return ret;
return ret;
return EOK;
return ret;
return ret;
return EOK;
int ret;
char *path;
if (!svc) {
return ENOMEM;
return ENOMEM;
return ENOMEM;
if (!path) {
return ENOMEM;
return ret;
return ENOMEM;
return ENOMEM;
return ENOMEM;
return ENOMEM;
if (debug_to_file) {
return ENOMEM;
return ret;
return EOK;
const char *name,
int restarts)
int ret;
return ret;
return ret;
int ret;
char *path;
if (!svc) {
return ENOMEM;
return ENOMEM;
return ENOMEM;
if (!path) {
return ENOMEM;
return ret;
return ret;
return ret;
return EIO;
return ENOMEM;
return ENOMEM;
return ENOMEM;
return ENOMEM;
if (debug_to_file) {
return ENOMEM;
return EOK;
const char *name,
int restarts)
int ret;
name));
return ret;
return ENOENT;
return ret;
int signum,
int count,
void *siginfo,
void *private_data)
static int monitor_cleanup(void)
int ret;
errno = 0;
return ret;
return EOK;
int status;
int kret;
bool killed;
killed = false;
errno = 0;
if (kret < 0) {
error = 0;
errno = 0;
killed = true;
} else if (pid != 0) {
error = 0;
killed = true;
if (!killed) {
} while (!killed);
#if HAVE_GETPGRP
error = 0;
errno = 0;
int signum,
int count,
void *siginfo,
void *private_data)
int ret;
if (ret == 0) {
int signum,
int count,
void *siginfo,
void *private_data)
int signum,
int count,
void *siginfo,
void *private_data)
const char *config_file,
if(!ctx) {
return ENOMEM;
goto done;
goto done;
goto done;
goto done;
goto done;
goto done;
goto done;
done:
return ret;
const char *file,
bool ignore_missing);
#ifdef HAVE_SYS_INOTIFY_H
if (!te) {
struct rewatch_ctx {
char *buf;
char *name;
if (!tmp_ctx) return;
if (!buf) {
goto done;
errno = 0;
goto done;
if (!name) {
goto done;
errno = 0;
goto done;
if (!cb) {
goto done;
if(!rw_ctx) {
goto done;
goto done;
done:
int err;
if (ret < 0) {
#ifdef HAVE_SYS_INOTIFY_H
return err;
if (fd_args < 0) {
return EINVAL;
if (ret < 0) {
return EINVAL;
file_ctx);
if (!tfd) {
return EIO;
if(!cb) {
return EIO;
return ENOMEM;
return err;
return EOK;
return EINVAL;
const char *file,
bool ignore_missing)
bool use_inotify;
if (ret < 0) {
return EOK;
return err;
true, &use_inotify);
return ret;
if (use_inotify) {
use_inotify = false;
if (!use_inotify) {
return ret;
const char *file,
bool ignore_missing)
if (ret < 0) {
return EOK;
return err;
if (!cb) {
return ENOMEM;
return ENOMEM;
return EIO;
return EOK;
const char *config_file)
char *rcachedir;
int num_providers;
int ret;
int error;
&rcachedir);
return ret;
errno = 0;
if (ret < 0) {
return EIO;
return EIO;
return EIO;
return EIO;
return EIO;
return ret;
/* Watch for changes to the DNS resolv.conf */
monitor_update_resolv,true);
return ret;
if (!tmp_ctx) {
return ENOMEM;
return ret;
return ret;
return ret;
num_providers = 0;
return ret;
if (num_providers > 0) {
return ret;
return EOK;
if (!mini) {
return ENOMEM;
return ENOMEM;
return EOK;
int ret;
return ENXIO;
if (!msg) {
return ENOMEM;
return ret;
const char *dbus_error_name;
int type;
if (!svc) {
if (!reply) {
goto done;
switch (type) {
case DBUS_MESSAGE_TYPE_ERROR:
if (!dbus_error_name) {
done:
return ENOMEM;
return EOK;
char **args;
int restart_delay;
if (!te) {
int opt;
int opt_daemon = 0;
int opt_interactive = 0;
int opt_version = 0;
int flags = 0;
int ret;
switch(opt) {
if (opt_version) {
return EXIT_SUCCESS;
if (uid != 0) {
if (!tmp_ctx) {
if (opt_config_file) {
if (!config_file) {
if (debug_to_file) {
if (ret) {
#ifdef USE_KEYRING
switch (ret) {
case ENOENT:
case EEXIST:
case EOK:
switch (ret) {
case EPERM:
case EACCES: