monitor.c revision df606157d22a633aab8cc7d532117a1b20870b58
75a6279dbae159d018ef812185416cf6df386c10Till Mossakowski Service monitor
967e5f3c25249c779575864692935627004d3f9eChristian Maeder Copyright (C) Simo Sorce 2008
89054b2b95a3f92e78324dc852f3d34704e2ca49Christian Maeder This program is free software; you can redistribute it and/or modify
967e5f3c25249c779575864692935627004d3f9eChristian Maeder it under the terms of the GNU General Public License as published by
967e5f3c25249c779575864692935627004d3f9eChristian Maeder the Free Software Foundation; either version 3 of the License, or
967e5f3c25249c779575864692935627004d3f9eChristian Maeder (at your option) any later version.
967e5f3c25249c779575864692935627004d3f9eChristian Maeder This program is distributed in the hope that it will be useful,
967e5f3c25249c779575864692935627004d3f9eChristian Maeder but WITHOUT ANY WARRANTY; without even the implied warranty of
967e5f3c25249c779575864692935627004d3f9eChristian Maeder MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
fd896e2068ad7e50aed66ac18c3720ea7ff2619fChristian Maeder GNU General Public License for more details.
7221c71b38c871ce66eee4537cb681d468308dfbChristian Maeder You should have received a copy of the GNU General Public License
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder along with this program. If not, see <http://www.gnu.org/licenses/>.
dea4c92f0c061d589c542d0640a18dab36dfbb46Christian Maeder/* Needed for res_init() */
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder/* ping time cannot be less then once every few seconds or the
ac19f8695aa1b2d2d1cd1319da2530edd8f46a96Christian Maeder * monitor will get crazy hammering children with messages */
7221c71b38c871ce66eee4537cb681d468308dfbChristian Maeder TALLOC_CTX *domain_ctx; /* Memory context for domain list */
bfa9e03532243ceb487f0384d0f6a447f1ce7670Till Mossakowski TALLOC_CTX *service_ctx; /* Memory context for services */
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maederstatic int start_service(struct mt_svc *mt_svc);
dea4c92f0c061d589c542d0640a18dab36dfbb46Christian Maederstatic int monitor_service_init(struct sbus_connection *conn, void *data);
e817ea5134dced9e0bcce1a9d6b8fe4f81d36e56Christian Maederstatic int service_send_ping(struct mt_svc *svc);
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maederstatic int service_signal_reset_offline(struct mt_svc *svc);
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maederstatic void ping_check(DBusPendingCall *pending, void *data);
97ee7048e63953c5617342ce38c30cbcb35cc0beChristian Maederstatic int service_check_alive(struct mt_svc *svc);
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maederstatic void set_tasks_checker(struct mt_svc *srv);
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maederstatic void set_global_checker(struct mt_ctx *ctx);
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maederstatic int monitor_kill_service (struct mt_svc *svc);
e817ea5134dced9e0bcce1a9d6b8fe4f81d36e56Christian Maederstatic int get_service_config(struct mt_ctx *ctx, const char *name,
97ee7048e63953c5617342ce38c30cbcb35cc0beChristian Maederstatic int get_provider_config(struct mt_ctx *ctx, const char *name,
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maederstatic int add_new_service(struct mt_ctx *ctx, const char *name);
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maederstatic int add_new_provider(struct mt_ctx *ctx, const char *name);
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maederstatic int mark_service_as_started(struct mt_svc *svc);
967e5f3c25249c779575864692935627004d3f9eChristian Maederstatic int monitor_cleanup(void);
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maederstatic void network_status_change_cb(enum network_change state,
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder struct mt_ctx *ctx = (struct mt_ctx *) cb_data;
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder DEBUG(9, ("A new route has appeared, signaling providers to reset offline status\n"));
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder for (iter = ctx->svc_list; iter; iter = iter->next) {
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder /* Don't signal services, only providers */
ee9eddfa6953868fd6fbaff0d9ff68675a13675aChristian Maeder/* dbus_get_monitor_version
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder * Return the monitor version over D-BUS */
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maederstatic int get_monitor_version(DBusMessage *message,
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder reply = dbus_message_new_method_return(message);
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder /* send reply back */
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maederstatic int add_svc_conn_spy(struct mt_svc *svc);
83814002b4922114cbe7e9ba728472a0bf44aac5Christian Maeder/* registers a new client.
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder * if operation is successful also sends back the Monitor version */
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maederstatic int client_registration(DBusMessage *message,
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder mini = talloc_get_type(data, struct mon_init_conn);
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;
done:
return ret;
if (!to) {
return ENOMEM;
return EOK;
char *monitor_address;
int ret;
return ret;
return ret;
int ret;
bool process_alive = true;
int ret;
switch (ret) {
case EOK:
case ECHILD:
process_alive = false;
if (process_alive) {
switch (ret) {
case EOK:
case ENXIO:
process_alive = false;
if (!process_alive) {
int status;
goto done;
errno = 0;
if (pid == 0) {
goto done;
goto done;
goto done;
done:
int ret;
return 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;
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;
int ret;
char *path;
if (!svc) {
return ENOMEM;
return ENOMEM;
return ENOMEM;
if (!path) {
return ENOMEM;
return ret;
return ENOMEM;
return ret;
return EOK;
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 EOK;
int ret;
name));
return ret;
return ENOENT;
return ret;
int signum,
int count,
void *siginfo,
void *private_data)
static int monitor_cleanup(void)
char *file;
int ret;
return ENOMEM;
errno = 0;
return errno;
return EOK;
int signum,
int count,
void *siginfo,
void *private_data)
int status;
int kret;
bool killed;
killed = false;
errno = 0;
if (kret < 0) {
error = 0;
errno = 0;
} else if (pid != 0) {
error = 0;
killed = true;
if (!killed) {
} while (!killed);
#if HAVE_GETPGRP
error = 0;
errno = 0;
exit(0);
int signum,
int count,
void *siginfo,
void *private_data)
int signum,
int count,
void *siginfo,
void *private_data)
int ret;
config_file));
return ret;
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;
#ifdef HAVE_SYS_INOTIFY_H
if (!te) {
struct rewatch_ctx {
char *buf;
char *name;
if (!tmp_ctx) return;
if (!buf) {
goto done;
total_len = 0;
goto done;
if (!name) {
goto done;
total_len = 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 use_inotify;
if (ret < 0) {
return err;
true, &use_inotify);
return ret;
if (use_inotify) {
use_inotify = false;
if (!use_inotify) {
if (!cb) {
return ENOMEM;
return ENOMEM;
return EIO;
return EOK;
const char *config_file)
int num_providers;
int ret;
return EIO;
return EIO;
return EIO;
return EIO;
return EIO;
return ret;
/* Watch for changes to the DNS resolv.conf */
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 (!reply) {
goto done;
switch (type) {
case DBUS_MESSAGE_TYPE_ERROR:
done:
int status;
if (pid == 0) {
return EOK;
return EINVAL;
return ECHILD;
return ENOMEM;
return EOK;
char **args;
int opt;
int opt_daemon = 0;
int opt_interactive = 0;
int flags = 0;
int ret;
switch(opt) {
if (uid != 0) {
if (!tmp_ctx) {
if (opt_config_file)
if(!config_file)
if (debug_to_file) {
if (ret) {