Safely closing tcp connections with a timer.

677 views
Skip to first unread message

Brian Nichols

unread,
Dec 1, 2015, 8:44:51 PM12/1/15
to libuv
I have a tcp connection with a timer.  I want to close or timeout the connection and safely release resources.  There will be many connections running concurrently.

1) Does uv_close() need to be called on the timer in addition to the tcp connection? 

2) Is the code below correct?

3) Is there a more efficient or elegant way to safely free a tcp connection with a timer?


struct my_connection {
uv_tcp_t socket;
uv_timer_t timer;
uv_connect_t connect;
bool timer_closed;
bool socket_closed;
} my_connection;

my_connection* open_connection(uv_loop_t* loop, struct sockaddr* addr) {
my_connection* conn = malloc(sizeof(my_connection));
conn->timer.data = conn;
conn->socket.data = conn;
conn->timer_closed = false;
conn->socket_closed = false;

uv_timer_init(loop, &conn->timer);
uv_timer_start(&conn->timer, timeout_cb, 1000, 0);
uv_tcp_init(loop, &conn->socket);
uv_tcp_connect(&conn->connect, &conn->socket, addr, connect_cb);
return conn;
}

void connect_cb(uv_connect_t* connect, int status) {
// Start writing to socket if connected.
// When finished, call close_connection().
}

void close_connection(my_connection* conn) {
uv_timer_stop(&conn->timer);

// Does timer need to be closed after stopping?
uv_close((uv_handle_t*)&conn->timer, timer_closed_cb);
uv_close((uv_handle_t*)&conn->socket, socket_closed_cb);
}

void timeout_cb(uv_timer_t* timer) {
my_connection* conn = timer->data;

// Does timer need to be closed on timeout?
uv_close((uv_handle_t*)&conn->timer, timer_closed_cb);
uv_close((uv_handle_t*)&conn->socket, socket_closed_cb);
}

void
timer_closed_cb(uv_handle_t* handle) {
my_connection* conn = handle->data;
conn->timer_closed = true;

if (conn->socket_closed)
free(conn);
}

void
socket_closed_cb(uv_handle_t* handle) {
my_connection* conn = handle->data;
conn->socket_closed = true;

if (conn->timer_closed)
free(conn);
}

Saúl Ibarra Corretgé

unread,
Dec 2, 2015, 5:41:27 AM12/2/15
to li...@googlegroups.com
Hi,

On 02/12/15 02:16, Brian Nichols wrote:
> I have a tcp connection with a timer. I want to close or timeout the
> connection and safely release resources. There will be many connections
> running concurrently.
>
> 1) Does uv_close() need to be called on the timer in addition to the tcp
> connection?
>

Yes. All handles need to be uv_close()-ed before you can free the memory
associated with them.

> 2) Is the code below correct?
>

Other than some missing error checking looks ok to me.

> 3) Is there a more efficient or elegant way to safely free a tcp
> connection with a timer?
>

A couple of quick notes:

You don't need to stop a timer if you are going to close it right after,
uv_close will take care of that.

You can use container_of in order to avoid storing pointers in the data
fields. Have a look at how we do it inside libuv.

The closing mechanism could be simplified by using a counter: you know 2
handles need to be closed, so pass the same close callback to both. In
it, decrease the counter (which you initialize to 2), when it reaches 0
you can free the structure.


Cheers,
> --
> You received this message because you are subscribed to the Google
> Groups "libuv" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to libuv+un...@googlegroups.com
> <mailto:libuv+un...@googlegroups.com>.
> To post to this group, send email to li...@googlegroups.com
> <mailto:li...@googlegroups.com>.
> Visit this group at http://groups.google.com/group/libuv.
> For more options, visit https://groups.google.com/d/optout.


--
Saúl Ibarra Corretgé
http://bettercallsaghul.com
Reply all
Reply to author
Forward
0 new messages