From patchwork Thu Feb 9 10:02:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Alin_N=C4=83stac?= X-Patchwork-Id: 726018 X-Patchwork-Delegate: blogic@openwrt.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from arrakis.dune.hu (arrakis.dune.hu [78.24.191.176]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vJttn0cF8z9s6n for ; Thu, 9 Feb 2017 21:03:13 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Y1XRPOUm"; dkim-atps=neutral Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id 987F9B912D1; Thu, 9 Feb 2017 11:03:06 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on arrakis.dune.hu X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00,FREEMAIL_FROM, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.1 Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP; Thu, 9 Feb 2017 11:03:06 +0100 (CET) Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id 3169EB911E8 for ; Thu, 9 Feb 2017 11:03:05 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 CL_IP_EQ_HELO_IP=-2 (check from: .gmail. - helo: .mail-wr0-f193.google. - helo-domain: .google.) FROM/MX_MATCHES_HELO(DOMAIN)=-2; rate: -7 Received: from mail-wr0-f193.google.com (mail-wr0-f193.google.com [209.85.128.193]) by arrakis.dune.hu (Postfix) with ESMTPS for ; Thu, 9 Feb 2017 11:03:03 +0100 (CET) Received: by mail-wr0-f193.google.com with SMTP id k90so11339957wrc.3 for ; Thu, 09 Feb 2017 02:03:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=8lVhzQVBiuFsoQAGXsEzW2PlDF1bzb4J9dZRuDjdMhA=; b=Y1XRPOUmVw96S4t84JurOlYOfUrvtaqKAKQ0RAw3j6c3GKdwPkEheI3GsatxCnwo4j BuADRr9ckz2rQmw7hezth8EfZfGnbXexpN7ewy4iQlER16Y24rWYwhEfJFE0FhTV1QuB rd0wwLkx6WwDQR5YB0vAkt8DvaJxO+X1E/P6P1PQIrb9S/gaYH6Y5sj0P/odUiEsElz4 uQ8HaOq6tUbEqHtp+OuF8FgSr8/whIcipcA4CFBB3m5IdsOxT4tplmrW1HT11gTtRsMo FsMLJnYMG49HKm0rtl8KbsmX4SwoNi9t5/U/wKydZaWX/iWQ3EhRbo00FXb2T8ctU/KH gYqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=8lVhzQVBiuFsoQAGXsEzW2PlDF1bzb4J9dZRuDjdMhA=; b=PelwB1viFQhbBZ+JnhhWquRIOCCP3nm+XR1iCv7ONuinE6Qyfbk4mox3tYkSbVPWDO PgjJ8m/sMQVdOHRCQUE35DEoyNzfjVnfLdufqLEzPCHHCcFvoyd8dnXAoIZ8hadKK4D2 40oug5eirHIKJulxc71ieEbngvewwpHXEXzOToBomI57FGfqwAFuAOXzwIwM0mLtYCLo ayihmAq+NvNBsotrbOyk2AIcIb8F6TDkeyWafb+jkDwKVLEP1xUi8vdyQ2ocsbJtYLR3 +d/pDGd0ioe8Ybj878E7e/ljrV8j9J3MFfxgYeS7vx2Ai3GPC+cu2QU6PIGmqFap60rz jCcA== X-Gm-Message-State: AMke39mQZTf4GXjCcl0kmmHpeGXMLCC2DD1f1giOEgpiZl4ebo85TWhwakmtz2QYAqz9zA== X-Received: by 10.223.175.49 with SMTP id z46mr2367523wrc.84.1486634581934; Thu, 09 Feb 2017 02:03:01 -0800 (PST) Received: from cplx250.edegem.eu.thmulti.com (14.125.146.82.ipv4.evonet.be. [82.146.125.14]) by smtp.gmail.com with ESMTPSA id b8sm17651368wrb.17.2017.02.09.02.03.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 09 Feb 2017 02:03:01 -0800 (PST) From: Alin Nastac To: John Crispin , openwrt-devel@lists.openwrt.org, lede-dev@lists.infradead.org Date: Thu, 9 Feb 2017 11:02:53 +0100 Message-Id: <1486634573-12258-1-git-send-email-alin.nastac@gmail.com> X-Mailer: git-send-email 1.7.12.4 Subject: [OpenWrt-Devel] [PATCH] procd: stop service using SIGKILL if SIGTERM failed to do so X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: openwrt-devel-bounces@lists.openwrt.org Sender: "openwrt-devel" SIGKILL is sent if instance process is still running after seconds after SIGTERM has been sent. To prevent another daemon process being launched before old process dies, the instance is kept until SIGCHLD confirms that service has been stopped. Signed-off-by: Alin Nastac --- service/instance.c | 44 +++++++++++++++++++++++++++++++++++++------- service/instance.h | 1 + service/service.c | 26 ++++++++++++++++---------- service/service.h | 3 +++ 4 files changed, 57 insertions(+), 17 deletions(-) diff --git a/service/instance.c b/service/instance.c index 018db3c..4d340fd 100644 --- a/service/instance.c +++ b/service/instance.c @@ -55,6 +55,7 @@ enum { INSTANCE_ATTR_SECCOMP, INSTANCE_ATTR_PIDFILE, INSTANCE_ATTR_RELOADSIG, + INSTANCE_ATTR_TERMTIMEOUT, __INSTANCE_ATTR_MAX }; @@ -79,6 +80,7 @@ static const struct blobmsg_policy instance_attr[__INSTANCE_ATTR_MAX] = { [INSTANCE_ATTR_SECCOMP] = { "seccomp", BLOBMSG_TYPE_STRING }, [INSTANCE_ATTR_PIDFILE] = { "pidfile", BLOBMSG_TYPE_STRING }, [INSTANCE_ATTR_RELOADSIG] = { "reload_signal", BLOBMSG_TYPE_INT32 }, + [INSTANCE_ATTR_TERMTIMEOUT] = { "term_timeout", BLOBMSG_TYPE_INT32 }, }; enum { @@ -389,8 +391,16 @@ instance_start(struct service_instance *in) return; } - if (in->proc.pending || !in->command) + if (!in->command) { + LOG("Not starting instance %s::%s, command not set\n", in->srv->name, in->name); return; + } + + if (in->proc.pending) { + if (in->halt) + in->restart = true; + return; + } instance_free_stdio(in); if (in->_stdout.fd.fd > -2) { @@ -408,7 +418,7 @@ instance_start(struct service_instance *in) } in->restart = false; - in->halt = !in->respawn; + in->halt = false; if (!in->valid) return; @@ -494,7 +504,11 @@ instance_timeout(struct uloop_timeout *t) in = container_of(t, struct service_instance, timeout); - if (!in->halt && (in->restart || in->respawn)) + if (in->halt) { + LOG("Instance %s::%s pid %d not stopped on SIGTERM, sending SIGKILL instead\n", + in->srv->name, in->name, in->proc.pid); + kill(in->proc.pid, SIGKILL); + } else if (in->restart || in->respawn) instance_start(in); } @@ -515,8 +529,19 @@ instance_exit(struct uloop_process *p, int ret) return; uloop_timeout_cancel(&in->timeout); + service_event("instance.stop", in->srv->name, in->name); + if (in->halt) { instance_removepid(in); + if (in->restart) + instance_start(in); + else { + struct service *s = in->srv; + + avl_delete(&s->instances.avl, &in->node.avl); + instance_free(in); + service_stopped(s); + } } else if (in->restart) { instance_start(in); } else if (in->respawn) { @@ -535,7 +560,6 @@ instance_exit(struct uloop_process *p, int ret) uloop_timeout_set(&in->timeout, in->respawn_timeout * 1000); } } - service_event("instance.stop", in->srv->name, in->name); } void @@ -546,6 +570,7 @@ instance_stop(struct service_instance *in) in->halt = true; in->restart = in->respawn = false; kill(in->proc.pid, SIGTERM); + uloop_timeout_set(&in->timeout, in->term_timeout * 1000); } static void @@ -559,10 +584,10 @@ instance_restart(struct service_instance *in) return; } - in->halt = false; + in->halt = true; in->restart = true; kill(in->proc.pid, SIGTERM); - instance_removepid(in); + uloop_timeout_set(&in->timeout, in->term_timeout * 1000); } static bool @@ -796,6 +821,8 @@ instance_config_parse(struct service_instance *in) if (!instance_config_parse_command(in, tb)) return false; + if (tb[INSTANCE_ATTR_TERMTIMEOUT]) + in->term_timeout = blobmsg_get_u32(tb[INSTANCE_ATTR_TERMTIMEOUT]); if (tb[INSTANCE_ATTR_RESPAWN]) { int i = 0; uint32_t vals[3] = { 3600, 5, 5}; @@ -933,8 +960,9 @@ instance_update(struct service_instance *in, struct service_instance *in_new) { bool changed = instance_config_changed(in, in_new); bool running = in->proc.pending; + bool stopping = in->halt; - if (!running) { + if (!running || stopping) { instance_config_move(in, in_new); instance_start(in); } else { @@ -967,6 +995,7 @@ instance_init(struct service_instance *in, struct service *s, struct blob_attr * in->config = config; in->timeout.cb = instance_timeout; in->proc.cb = instance_exit; + in->term_timeout = 5; in->_stdout.fd.fd = -2; in->_stdout.stream.string_data = true; @@ -999,6 +1028,7 @@ void instance_dump(struct blob_buf *b, struct service_instance *in, int verbose) blobmsg_add_u32(b, "pid", in->proc.pid); if (in->command) blobmsg_add_blob(b, in->command); + blobmsg_add_u32(b, "term_timeout", in->term_timeout); if (!avl_is_empty(&in->errors.avl)) { struct blobmsg_list_node *var; diff --git a/service/instance.h b/service/instance.h index 3cc2009..78999c8 100644 --- a/service/instance.h +++ b/service/instance.h @@ -59,6 +59,7 @@ struct service_instance { char *seccomp; char *pidfile; + uint32_t term_timeout; uint32_t respawn_timeout; uint32_t respawn_threshold; uint32_t respawn_retry; diff --git a/service/service.c b/service/service.c index 2c73901..0584ee0 100644 --- a/service/service.c +++ b/service/service.c @@ -59,11 +59,10 @@ service_instance_update(struct vlist_tree *tree, struct vlist_node *node_new, instance_update(in_o, in_n); instance_free(in_n); } else if (in_o) { - DEBUG(2, "Free instance %s::%s\n", in_o->srv->name, in_o->name); + DEBUG(2, "Stop instance %s::%s\n", in_o->srv->name, in_o->name); instance_stop(in_o); - instance_free(in_o); } else if (in_n) { - DEBUG(2, "Create instance %s::%s\n", in_n->srv->name, in_n->name); + DEBUG(2, "Start instance %s::%s\n", in_n->srv->name, in_n->name); instance_start(in_n); } blob_buf_init(&b, 0); @@ -80,7 +79,7 @@ service_alloc(const char *name) strcpy(new_name, name); vlist_init(&s->instances, avl_strcmp, service_instance_update); - s->instances.keep_old = true; + s->instances.no_delete = true; s->name = new_name; s->avl.key = s->name; INIT_LIST_HEAD(&s->validators); @@ -149,13 +148,8 @@ service_update(struct service *s, struct blob_attr **tb, bool add) static void service_delete(struct service *s) { - service_event("service.stop", s->name, NULL); vlist_flush_all(&s->instances); - avl_delete(&services, &s->avl); - trigger_del(s); - free(s->trigger); - free(s); - service_validate_del(s); + service_stopped(s); } enum { @@ -606,6 +600,18 @@ service_start_early(char *name, char *cmdline) return service_handle_set(NULL, NULL, NULL, "add", b.head); } +void service_stopped(struct service *s) +{ + if (avl_is_empty(&s->instances.avl)) { + service_event("service.stop", s->name, NULL); + avl_delete(&services, &s->avl); + trigger_del(s); + free(s->trigger); + free(s); + service_validate_del(s); + } +} + void service_event(const char *type, const char *service, const char *instance) { if (!ctx) diff --git a/service/service.h b/service/service.h index c3f2964..d4f0a83 100644 --- a/service/service.h +++ b/service/service.h @@ -50,7 +50,10 @@ void service_validate_add(struct service *s, struct blob_attr *attr); void service_validate_dump(struct blob_buf *b, struct service *s); void service_validate_dump_all(struct blob_buf *b, char *p, char *s); int service_start_early(char *name, char *cmdline); +void service_stopped(struct service *s); void service_validate_del(struct service *s); void service_event(const char *type, const char *service, const char *instance); + + #endif