libstrophe leaves connections in CLOSE_WAIT sate

38 views
Skip to first unread message

Mateusz Viste

unread,
Mar 9, 2020, 12:04:49 PM3/9/20
to libstrophe
Hello,

I am using libstrophe to monitor my home jabber server - basically connecting to the server, and then disconnecting right away. My application does that every few minutes.

I noticed that the XMPP connections I open are not being closed - they are left in a 'CLOSE_WAIT' state, visible in a netstat output and they accumulate over time:

tcp        1      0 192.168.1.41:46144      xx.xx.xx.xx:5222      CLOSE_WAIT  30651/./test     
tcp       51      0 192.168.1.41:46168      xx.xx.xx.xx:5222      CLOSE_WAIT  30651/./test     
tcp       46      0 192.168.1.41:46152      xx.xx.xx.xx:5222      CLOSE_WAIT  30651/./test     
tcp      300      0 192.168.1.41:46132      xx.xx.xx.xx:5222      CLOSE_WAIT  30651/./test     
tcp      468      0 192.168.1.41:46130      xx.xx.xx.xx:5222      CLOSE_WAIT  30651/./test     
tcp        1      0 192.168.1.41:46176      xx.xx.xx.xx:5222      CLOSE_WAIT  30651/./test     
tcp        1      0 192.168.1.41:46122      xx.xx.xx.xx:5222      CLOSE_WAIT  30651/./test      
tcp      226      0 192.168.1.41:46162      xx.xx.xx.xx:5222      CLOSE_WAIT  30651/./test     
tcp      468      0 192.168.1.41:46158      xx.xx.xx.xx:5222      CLOSE_WAIT  30651/./test      
tcp        1      0 192.168.1.41:46112      xx.xx.xx.xx:5222      CLOSE_WAIT  30651/./test      
tcp      468      0 192.168.1.41:46154      xx.xx.xx.xx:5222      CLOSE_WAIT  30651/./test
(etc...)

I can only assume that I am using the library wrong. This is what I do (I removed all error checking for readability):

void do_test() {
  xmpp_ctx_t *xmpp_ctx = NULL;
  xmpp_conn_t *xmpp_conn = NULL;

  /* initialize the xmpp library, context and connection structures */
  xmpp_initialize();
  xmpp_ctx = xmpp_ctx_new(NULL, NULL);
  xmpp_conn = xmpp_conn_new(xmpp_ctx);

  /* setup auth information */
  xmpp_conn_set_jid(xmpp_conn, "mylogin");
  xmpp_conn_set_pass(xmpp_conn, "mypassword");
  xmpp_conn_set_flags(xmpp_conn, XMPP_CONN_FLAG_TRUST_TLS);

  /* connect */
  xmpp_connect_client(xmpp_conn, altserverptr, c->altport, conn_handler, xmpp_ctx);
  while (conn_handler_done_flag == 0) xmpp_run_once(xmpp_ctx, 5000);

  /* cleanup and shutdown */
  xmpp_disconnect(xmpp_conn);
  xmpp_run_once(xmpp_ctx, 100);
  xmpp_conn_release(xmpp_conn);
  xmpp_ctx_free(xmpp_ctx);
  xmpp_shutdown();
}

Any idea what I am missing?

best regards,
Mateusz

Dmitry Podgorny

unread,
Mar 9, 2020, 1:51:25 PM3/9/20
to libstrophe
Hi Mateusz,

Your code doesn't wait for the server to close the stream. Basically, you send </stream:stream> by calling xmpp_disconnect(), but you need to wait in the event loop, so libstrophe receives </stream:stream> from the server and handle it. You won't have the issue if you continue running xmpp_run_once() until your connection handler receives XMPP_CONN_DISCONNECT event. The easiest way to rewrite the example is to move xmpp_disconnect() to where conn_handler_done_flag is set. And the flag should be set when XMPP_CONN_DISCONNECT happens. This change will also simplify your code.

This issue has been fixed in master recently: https://github.com/strophe/libstrophe/commit/133abd096db609274e9ee05a75cda387ef6b9f0e

Check the example below or examples/basic.c and examples/bot.c.

int message_handler(xmpp_conn_t *conn,
                    xmpp_stanza_t *stanza,
                    void *userdata)
{
    ...
    if (quit) {
        xmpp_disconnect(conn);
    }
}

void conn_handler(xmpp_conn_t *const conn,
                  const xmpp_conn_event_t status,
                  const int error,
                  xmpp_stream_error_t *const stream_error,
                  void *const userdata)
{
    ...
    if (status == XMPP_CONN_DISCONNECT) {
        conn_handler_done_flag = 1;
    }
}

int main()
{
    ...
    while (conn_handler_done_flag == 0) {
        xmpp_run_once(xmpp_ctx, 5000);
    }

    xmpp_conn_release(xmpp_conn);
    xmpp_ctx_free(xmpp_ctx);
    xmpp_shutdown();

    return 0;
}

Mateusz Viste

unread,
Mar 9, 2020, 3:57:09 PM3/9/20
to libstrophe
Hello Dmitry,

Thank you for your kind reply. I was suspecting indeed that I probably should give the library some time for cleaning up, but I was also expecting it to force-close its socket when explicitly told that I am no longer interested in playing (even though it is not very "polite" on my part). I understand now that this behavior has been improved, so I will upgrade to master.

Thank you very much for your valuable pointers!

best regards,
Mateusz
Reply all
Reply to author
Forward
0 new messages