Skip to content

Commit

Permalink
closingd: Ensure proper closing of TCP socket.
Browse files Browse the repository at this point in the history
  • Loading branch information
ZmnSCPxj authored and rustyrussell committed May 9, 2018
1 parent 80b298a commit 926b41b
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 0 deletions.
1 change: 1 addition & 0 deletions closingd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ CLOSINGD_COMMON_OBJS := \
common/permute_tx.o \
common/ping.o \
common/read_peer_msg.o \
common/socket_close.o \
common/status.o \
common/status_wire.o \
common/subdaemon.o \
Expand Down
6 changes: 6 additions & 0 deletions closingd/closing.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <common/peer_billboard.h>
#include <common/peer_failed.h>
#include <common/read_peer_msg.h>
#include <common/socket_close.h>
#include <common/status.h>
#include <common/subdaemon.h>
#include <common/type_to_string.h>
Expand Down Expand Up @@ -581,6 +582,11 @@ int main(int argc, char *argv[])
offer[LOCAL]);

/* We're done! */
/* Properly close the channel first. */
if (!socket_close(PEER_FD))
status_unusual("Closing and draining peerfd gave error: %s",
strerror(errno));
/* Sending the below will kill us! */
wire_sync_write(REQ_FD, take(towire_closing_complete(NULL)));
tal_free(ctx);
daemon_shutdown();
Expand Down
1 change: 1 addition & 0 deletions common/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ COMMON_SRC_NOGEN := \
common/ping.c \
common/pseudorand.c \
common/read_peer_msg.c \
common/socket_close.c \
common/sphinx.c \
common/status.c \
common/status_wire.c \
Expand Down
47 changes: 47 additions & 0 deletions common/socket_close.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "socket_close.h"
#include <ccan/noerr/noerr.h>
#include <errno.h>
#include <sys/socket.h>
#include <unistd.h>

/*
Simplified (minus all the error checks):
shutdown(fd, SHUT_WR);
for (;;) {
char unused[64]
sys_res = read(fd, unused, 64);
if (sys_res == 0)
break;
}
close(fd);
*/

bool socket_close(int fd)
{
char unused[64];
int sys_res;

sys_res = shutdown(fd, SHUT_WR);
if (sys_res < 0) {
close_noerr(fd);
return false;
}

for (;;) {
do {
sys_res = read(fd, unused, sizeof(unused));
} while (sys_res < 0 && errno == EINTR);
if (sys_res < 0) {
close_noerr(fd);
return false;
}
if (sys_res == 0)
break;
}

if (close(fd) < 0)
return false;
else
return true;
}
23 changes: 23 additions & 0 deletions common/socket_close.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* common/socket_close - Properly close a socket,
* ensuring that any data we write just before
* the close has been transmitted to the other
* side, and ignoring any data the other side
* has sent at the time the close was started.
*
* Reference:
*
* http://ia800504.us.archive.org/3/items/TheUltimateSo_lingerPageOrWhyIsMyTcpNotReliable/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable.html
*/
#ifndef LIGHTNING_COMMON_SOCKET_CLOSE_H
#define LIGHTNING_COMMON_SOCKET_CLOSE_H
#include "config.h"
#include <stdbool.h>

/* Return false if something failed, true if
* nothing failed.
* If something failed, error is stored in
* `errno.
*/
bool socket_close(int fd);

#endif /* LIGHTNING_COMMON_SOCKET_CLOSE_H */

0 comments on commit 926b41b

Please sign in to comment.