Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions src/conns.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "conns.h"
#include "heap.h"
#include "log.h"
#include "sock.h"
#include "stats.h"

void conn_struct_init(struct conn_s *connptr) {
Expand Down Expand Up @@ -82,14 +83,10 @@ void conn_destroy_contents (struct conn_s *connptr)
assert (connptr != NULL);

if (connptr->client_fd != -1)
if (close (connptr->client_fd) < 0)
log_message (LOG_INFO, "Client (%d) close message: %s",
connptr->client_fd, strerror (errno));
close_socket (connptr->client_fd);
connptr->client_fd = -1;
if (connptr->server_fd != -1)
if (close (connptr->server_fd) < 0)
log_message (LOG_INFO, "Server (%d) close message: %s",
connptr->server_fd, strerror (errno));
close_socket (connptr->server_fd);
connptr->server_fd = -1;

if (connptr->cbuffer)
Expand Down
1 change: 1 addition & 0 deletions src/reqs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,7 @@ static void relay_connection (struct conn_s *connptr)
if (write_buffer (connptr->server_fd, connptr->cbuffer) < 0)
break;
}
shutdown (connptr->server_fd, SHUT_WR);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why another shutdown() here ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It mirrors the pre-existing shutdown(client_fd, SHUT_WR) above. Both initiate the close handshake early so that by the time close_socket() runs in conn_destroy_contents, the remote FIN may already have arrived and the drain loop returns immediately.


return;
}
Expand Down
37 changes: 37 additions & 0 deletions src/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,43 @@ int opensock (const char *host, int port, const char *bind_to)
return sockfd;
}

/*
* Gracefully close a socket by completing the TCP close handshake.
* Send FIN via shutdown(SHUT_WR), then drain remaining data until
* the remote FIN arrives (read returns 0). This keeps the fd open
* until both sides have exchanged FINs, preventing the socket from
* being orphaned in FIN_WAIT_2.
*
* Without this, close() orphans the socket while still in FIN_WAIT_2.
* Linux reaps orphaned FIN_WAIT_2 via net.ipv4.tcp_fin_timeout, but
* OpenBSD has no equivalent, so they persist indefinitely.
*/
void close_socket (int fd)
{
char drain[4096];
ssize_t n;
struct timeval tv;

shutdown (fd, SHUT_WR);

tv.tv_sec = 10;
tv.tv_usec = 0;
setsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv));

for (;;) {
n = read (fd, drain, sizeof (drain));
if (n > 0)
continue;
if (n == 0)
break;
if (errno == EINTR)
continue;
break;
}

close (fd);
}

/*
* Set the socket to non blocking -rjkaes
*/
Expand Down
1 change: 1 addition & 0 deletions src/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ union sockaddr_union {
extern int opensock (const char *host, int port, const char *bind_to);
extern int listen_sock (const char *addr, uint16_t port, sblist* listen_fds);

extern void close_socket (int fd);
extern int socket_nonblocking (int sock);
extern int socket_blocking (int sock);

Expand Down