diff options
author | Michal Schmidt <mschmidt@redhat.com> | 2012-01-20 23:44:22 +0100 |
---|---|---|
committer | Michal Schmidt <mschmidt@redhat.com> | 2012-01-20 23:57:54 +0100 |
commit | 1a710b430b7e5fa036ee5c03e14e60f725df5baf (patch) | |
tree | 903715a60ac406e85493edafcc3720fd900ebc76 /src/socket.c | |
parent | 229b5d55f620704d62b91d824f429a6cf07e070c (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
Diffstat (limited to 'src/socket.c')
-rw-r--r-- | src/socket.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/src/socket.c b/src/socket.c index b2bb080263..7409aea5ee 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 */ |