Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Register
  • Sign in
  • L libsoup
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
  • Issues 174
    • Issues 174
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 14
    • Merge requests 14
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Container Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • GNOMEGNOME
  • libsoup
  • Issues
  • #181
Closed
Open
Issue created Jan 16, 2020 by Benjamin Reikowski@reikowski

soup WebSocket server asserts when a client is closing the connection

Hello,

I'm using the libsoup websocket server and recently updated my libsoup from 2.64.2 to 2.68.3 due to a bug that has been fixed with https://github.com/GNOME/libsoup/commit/35f1bac5ff9ec694e64b65e51f0e7a3226aa3aaf

Since then I have a new problem, which I better explain using this simple example code:

static void websocket_client_message_cb(SoupWebsocketConnection *ws, SoupWebsocketDataType type, GBytes *message, gpointer user_data) {
    (void) ws; (void) type; (void) message; (void) user_data;
    g_message("%s", __func__);
}

static void websocket_client_closed_cb(SoupWebsocketConnection *ws, gpointer user_data) {
    (void) user_data;
    g_object_unref(ws);
    g_message("%s", __func__);
}

static void websocket_client_error_cb(SoupWebsocketConnection *ws, GError *error, gpointer user_data)'{
    (void) ws; (void) error; (void) user_data;
    g_message("%s", __func__);
}

static void websocket_client_connect_cb(SoupServer *server, SoupWebsocketConnection *ws,
        const char *path, SoupClientContext *client, gpointer user_data) {
    (void) server; (void) client; (void) user_data; (void) path;
    g_object_ref(ws);
    g_signal_connect(ws, "message", G_CALLBACK(websocket_client_message_cb), NULL);
    g_signal_connect(ws, "closed",  G_CALLBACK(websocket_client_closed_cb), NULL);
    g_signal_connect(ws, "error",   G_CALLBACK(websocket_client_error_cb), NULL);
    g_message("%s", __func__);
}

int main(int argc, char* argv[]) {
    GMainLoop *mainloop = g_main_loop_new(0, FALSE);

    /* play here */
    GError *error = NULL;
    SoupServer *server = soup_server_new(NULL, NULL);
    soup_server_listen_all(server, 33333, 0, &error);
    g_assert_no_error(error);
    soup_server_add_websocket_handler(server, "/", NULL, NULL, websocket_client_connect_cb, NULL, NULL);
    g_message("ws server started");

    /* run mainloop */
    g_main_loop_run(mainloop);
}

This starts a simple websocket server with 1 handler and registers the usual signal callbacks. The new problem is, every time a websocket client disconnects from this server, I run into this g_assert (with G_MESSAGES_DEBUG=all):

(gdb) run
Starting program: /home/root/main2
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/libthread_db.so.1".
** Message: 15:18:58.822: ws server started
** Message: 15:19:07.256: websocket_client_connect_cb
(process:12326): libsoup-DEBUG: 15:19:08.896: stopping input source
(process:12326): libsoup-DEBUG: 15:19:08.896: received control frame 8 with 0 payload
(process:12326): libsoup-DEBUG: 15:19:08.897: responding to close request
(process:12326): libsoup-DEBUG: 15:19:08.897: sent frame
(process:12326): libsoup-DEBUG: 15:19:08.897: closing io stream
[New Thread 0x76823460 (LWP 12329)]
(process:12326): libsoup-DEBUG: 15:19:08.901: queued 8 frame of len 4
(process:12326): libsoup-DEBUG: 15:19:08.902: waiting 5 seconds for peer to close io
(process:12326): libsoup-DEBUG: 15:19:08.902: closed: completed io stream close
** Message: 15:19:08.903: websocket_client_closed_cb
**
libsoup:ERROR:../libsoup-2.68.3/libsoup/soup-websocket-connection.c:1445:soup_websocket_connection_finalize: assertion failed: (!pv->input_source)
Bail out! libsoup:ERROR:../libsoup-2.68.3/libsoup/soup-websocket-connection.c:1445:soup_websocket_connection_finalize: assertion failed: (!pv->input_source)

Thread 1 "main2" received signal SIGABRT, Aborted.
__libc_do_syscall () at libc-do-syscall.S:49
49      libc-do-syscall.S: No such file or directory.
(gdb) bt
#0  0x76c80c46 in __libc_do_syscall () at libc-do-syscall.S:49
#1  0x76c8dfa4 in __libc_signal_restore_set (set=0x7efff758) at ../sysdeps/unix/sysv/linux/internal-signals.h:84
#2  0x76c8dfa4 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:48
#3  0x76c806e6 in __GI_abort () at abort.c:79
#4  0x76f57bde in g_assertion_message
    (domain=domain@entry=0x76ef2f1c "libsoup", file=file@entry=0x76ef93b8 "../libsoup-2.68.3/libsoup/soup-websocket-connection.c", line=line@entry=1445, func=func@entry=0x76efde48 <__FUNCTION__.3022
#5  0x76f57c50 in g_assertion_message_expr
    (domain=0x76ef2f1c "libsoup", file=0x76ef93b8 "../libsoup-2.68.3/libsoup/soup-websocket-connection.c", line=line@entry=1445, func=0x76efde48 <__FUNCTION__.30297> "soup_websocket_connection_fina8
#6  0x76eea218 in soup_websocket_connection_finalize (object=0x2c098 [SoupWebsocketConnection]) at ../libsoup-2.68.3/libsoup/soup-websocket-connection.c:1445
#7  0x76d68528 in g_object_unref (_object=<optimized out>) at ../glib-2.62.4/gobject/gobject.c:3382
#8  0x76d68528 in g_object_unref (_object=0x2c098) at ../glib-2.62.4/gobject/gobject.c:3274
#9  0x76eea8c0 in on_iostream_closed (source=<optimized out>, result=<optimized out>, user_data=0x2c098) at ../libsoup-2.68.3/libsoup/soup-websocket-connection.c:297
#10 0x76e0bbec in g_task_return_now (task=0x2e400 [GTask]) at ../glib-2.62.4/gio/gtask.c:1212
#11 0x76e0c456 in g_task_return (task=0x2e400 [GTask], type=<optimized out>) at ../glib-2.62.4/gio/gtask.c:1281
#12 0x76e0ca88 in g_task_return (type=G_TASK_RETURN_SUCCESS, task=<optimized out>) at ../glib-2.62.4/gio/gtask.c:1797
#13 0x76e0ca88 in g_task_return_boolean (task=<optimized out>, result=<optimized out>) at ../glib-2.62.4/gio/gtask.c:1801
#14 0x76decf84 in async_ready_close_callback_wrapper (source_object=<optimized out>, res=0x2e478, user_data=0x2e400) at ../glib-2.62.4/gio/giostream.c:455
#15 0x76e0bbec in g_task_return_now (task=0x2e478 [GTask]) at ../glib-2.62.4/gio/gtask.c:1212
#16 0x76e0c456 in g_task_return (task=0x2e478 [GTask], type=<optimized out>) at ../glib-2.62.4/gio/gtask.c:1281
#17 0x76e0ca88 in g_task_return (type=G_TASK_RETURN_SUCCESS, task=<optimized out>) at ../glib-2.62.4/gio/gtask.c:1797
#18 0x76e0ca88 in g_task_return_boolean (task=<optimized out>, result=<optimized out>) at ../glib-2.62.4/gio/gtask.c:1801
#19 0x76ed0f34 in close_async_complete (object=0xc268 [GTcpConnection], result=0x2e4f0, user_data=0x2e478) at ../libsoup-2.68.3/libsoup/soup-io-stream.c:147
#20 0x76e0bbec in g_task_return_now (task=0x2e4f0 [GTask]) at ../glib-2.62.4/gio/gtask.c:1212
#21 0x76e0c456 in g_task_return (task=0x2e4f0 [GTask], type=<optimized out>) at ../glib-2.62.4/gio/gtask.c:1281
#22 0x76e0ca88 in g_task_return (type=G_TASK_RETURN_SUCCESS, task=<optimized out>) at ../glib-2.62.4/gio/gtask.c:1797
--Type <RET> for more, q to quit, c to continue without paging--
#23 0x76e0ca88 in g_task_return_boolean (task=<optimized out>, result=<optimized out>) at ../glib-2.62.4/gio/gtask.c:1801
#24 0x76decf84 in async_ready_close_callback_wrapper (source_object=<optimized out>, res=0x2e568, user_data=0x2e4f0) at ../glib-2.62.4/gio/giostream.c:455
#25 0x76e0bbec in g_task_return_now (task=0x2e568 [GTask]) at ../glib-2.62.4/gio/gtask.c:1212
#26 0x76e0bc20 in complete_in_idle_cb (task=0x2e568) at ../glib-2.62.4/gio/gtask.c:1226
#27 0x76f3d08a in g_main_dispatch (context=0x11f78) at ../glib-2.62.4/glib/gmain.c:3179
#28 0x76f3d08a in g_main_context_dispatch (context=context@entry=0x11f78) at ../glib-2.62.4/glib/gmain.c:3844
#29 0x76f3d2f8 in g_main_context_iterate (context=0x11f78, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib-2.62.4/glib/gmain.c:3917
#30 0x76f3d534 in g_main_loop_run (loop=0x13430) at ../glib-2.62.4/glib/gmain.c:4111
#31 0x00008c7c in main (argc=1, argv=0x7efffd44) at main2.c:112
(gdb) 

This assertion is new and did not happen before the commit I mentioned at the beginning. I do NOT run into this g_assert if I'm either not using g_object_unref(ws) in function websocket_client_closed_cb or delay it by 1s. But I HAVE to use g_object_ref(ws) in function websocket_client_connect_cb otherwise the SoupWebsocketConnection *ws would not survive.

At last, I used valgrind on my example code and found out that it's pretty leaky w/o g_object_unref(ws).

The corresponding mails can be found here: https://mail.gnome.org/archives/libsoup-list/2020-January/msg00000.html

With best regards

Edited Jan 16, 2020 by Benjamin Reikowski
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking