From b57bafa73c2e035c216de8fb7933d751d456a93b Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 5 Mar 2012 22:47:54 +0100
Subject: [PATCH] socket: fail the socket if the service keeps dying on start
If the service reaches the start limit, mark the sockets that activate
it as failed (with the result code 'service-broken').
This way the sockets won't act as tarpits for clients connecting to
them.
(cherry picked from commit c2f3480897b51dd9b2137f1eeddb4c851e9c6e3b)
Conflicts:
src/service.c
src/socket.c
src/socket.h
---
src/service.c | 7 ++++---
src/socket.c | 9 ++++++---
src/socket.h | 2 +-
3 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/service.c b/src/service.c
index f99ee60..950e495 100644
--- a/src/service.c
+++ b/src/service.c
@@ -1375,7 +1375,7 @@ static int service_search_main_pid(Service *s) {
return 0;
}
-static void service_notify_sockets_dead(Service *s) {
+static void service_notify_sockets_dead(Service *s, bool broken) {
Iterator i;
Unit *u;
@@ -1388,7 +1388,7 @@ static void service_notify_sockets_dead(Service *s) {
SET_FOREACH(u, s->meta.dependencies[UNIT_TRIGGERED_BY], i)
if (u->meta.type == UNIT_SOCKET)
- socket_notify_service_dead(SOCKET(u));
+ socket_notify_service_dead(SOCKET(u), broken);
return;
}
@@ -1450,7 +1450,7 @@ static void service_set_state(Service *s, ServiceState state) {
state == SERVICE_FINAL_SIGKILL ||
state == SERVICE_FAILED ||
state == SERVICE_AUTO_RESTART)
- service_notify_sockets_dead(s);
+ service_notify_sockets_dead(s, false);
if (state != SERVICE_START_PRE &&
state != SERVICE_START &&
@@ -2275,6 +2275,7 @@ static int service_start(Unit *u) {
/* Make sure we don't enter a busy loop of some kind. */
if (!ratelimit_test(&s->ratelimit)) {
log_warning("%s start request repeated too quickly, refusing to start.", u->meta.id);
+ service_notify_sockets_dead(s, true);
return -ECANCELED;
}
diff --git a/src/socket.c b/src/socket.c
index 8bce18c..4b85528 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -2016,7 +2016,7 @@ int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds) {
return 0;
}
-void socket_notify_service_dead(Socket *s) {
+void socket_notify_service_dead(Socket *s, bool broken) {
assert(s);
/* The service is dead. Dang!
@@ -2025,8 +2025,11 @@ void socket_notify_service_dead(Socket *s) {
* services. */
if (s->state == SOCKET_RUNNING) {
- log_debug("%s got notified about service death.", s->meta.id);
- socket_enter_listening(s);
+ log_debug("%s got notified about service death (broken: %s)", s->meta.id, yes_no(broken));
+ if (broken)
+ socket_enter_stop_pre(s, false);
+ else
+ socket_enter_listening(s);
}
}
diff --git a/src/socket.h b/src/socket.h
index 4fc2cbe..31b9552 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -137,7 +137,7 @@ struct Socket {
int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds);
/* Called from the service when it shut down */
-void socket_notify_service_dead(Socket *s);
+void socket_notify_service_dead(Socket *s, bool broken);
/* Called from the mount code figure out if a mount is a dependency of
* any of the sockets of this socket */