summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Schmidt <mschmidt@redhat.com>2012-01-20 23:44:22 +0100
committerMichal Schmidt <mschmidt@redhat.com>2012-01-20 23:57:54 +0100
commit1a710b430b7e5fa036ee5c03e14e60f725df5baf (patch)
tree903715a60ac406e85493edafcc3720fd900ebc76
parent229b5d55f620704d62b91d824f429a6cf07e070c (diff)
socket: don't fail the socket on ENOTCONN
Albert Strasheim reported a socket unit with Accept=yes was failing sometimes. getpeername() returns ENOTCONN if the connection was killed by TCP RST. The socket unit must not fail when it happens. Reproducer available at: https://bugzilla.redhat.com/show_bug.cgi?id=783344
-rw-r--r--src/socket.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/src/socket.c b/src/socket.c
index b2bb0802..7409aea5 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -1368,7 +1368,8 @@ static void socket_enter_running(Socket *s, int cfd) {
/* Flush all sockets by closing and reopening them */
socket_close_fds(s);
- if ((r = socket_watch_fds(s)) < 0) {
+ r = socket_watch_fds(s);
+ if (r < 0) {
log_warning("%s failed to watch sockets: %s", UNIT(s)->id, strerror(-r));
socket_enter_stop_pre(s, false);
}
@@ -1390,9 +1391,11 @@ static void socket_enter_running(Socket *s, int cfd) {
break;
}
- if (!pending)
- if ((r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, true, &error, NULL)) < 0)
+ if (!pending) {
+ r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, true, &error, NULL);
+ if (r < 0)
goto fail;
+ }
socket_set_state(s, SOCKET_RUNNING);
} else {
@@ -1405,13 +1408,23 @@ static void socket_enter_running(Socket *s, int cfd) {
return;
}
- if ((r = socket_instantiate_service(s)) < 0)
+ r = socket_instantiate_service(s);
+ if (r < 0)
goto fail;
- if ((r = instance_from_socket(cfd, s->n_accepted, &instance)) < 0)
- goto fail;
+ r = instance_from_socket(cfd, s->n_accepted, &instance);
+ if (r < 0) {
+ if (r != -ENOTCONN)
+ goto fail;
+
+ /* ENOTCONN is legitimate if TCP RST was received.
+ * This connection is over, but the socket unit lives on. */
+ close_nointr_nofail(cfd);
+ return;
+ }
- if (!(prefix = unit_name_to_prefix(UNIT(s)->id))) {
+ prefix = unit_name_to_prefix(UNIT(s)->id);
+ if (!prefix) {
free(instance);
r = -ENOMEM;
goto fail;
@@ -1426,7 +1439,8 @@ static void socket_enter_running(Socket *s, int cfd) {
goto fail;
}
- if ((r = unit_add_name(UNIT_DEREF(s->service), name)) < 0) {
+ r = unit_add_name(UNIT_DEREF(s->service), name);
+ if (r < 0) {
free(name);
goto fail;
}
@@ -1440,13 +1454,15 @@ static void socket_enter_running(Socket *s, int cfd) {
unit_choose_id(UNIT(service), name);
free(name);
- if ((r = service_set_socket_fd(service, cfd, s)) < 0)
+ r = service_set_socket_fd(service, cfd, s);
+ if (r < 0)
goto fail;
cfd = -1;
s->n_connections ++;
- if ((r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, true, &error, NULL)) < 0)
+ r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, true, &error, NULL);
+ if (r < 0)
goto fail;
/* Notify clients about changed counters */