webdis process crashes whenever a browser window maintaining a websocket connection closes
Hi, I am trying out webdis as a pub sub web socket frontend. Here's the relevant code creating and tearing down the web socket connection:
var jsonSocket = new WebSocket('ws://0.0.0.0:8081/.json');
jsonSocket.onmessage = function(){...}
jsonSocket.onclose = function(){
jsonSocket.send(JSON.stringify(["UNSUBSCRIBE", key]));
}
$(window).bind("beforeunload", function(){jsonSocket.close()});
If I reload the page running this code, webdis exits on the server. Even if I am doing something wrong, this is probably something that makes webdis -an otherwise excellent piece of kit I use all the time- too frail a web socket frontend for Redis.
Here's the relevant trace:
*** glibc detected *** ./webdis: munmap_chunk(): invalid pointer: 0x00007fbaf00062f0 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x79616)[0x7fbb0a726616]
./webdis[0x41183d]
./webdis[0x411868]
./webdis[0x41229a]
./webdis[0x41248f]
./webdis[0x4124eb]
./webdis[0x40914e]
./webdis[0x401ff5]
./webdis[0x4079d4]
./webdis[0x402e09]
/usr/lib64/libevent-2.0.so.5(event_base_loop+0x1fc)[0x7fbb0ac65a3c]
./webdis[0x403219]
/lib64/libpthread.so.0(+0x7ddb)[0x7fbb0aa41ddb]
/lib64/libc.so.6(clone+0x6d)[0x7fbb0a78fa1d]
======= Memory map: ========
00400000-00425000 r-xp 00000000 ca:10 396600 /mnt/shared/webdis/webdis
00625000-00626000 rw-p 00025000 ca:10 396600 /mnt/shared/webdis/webdis
009bb000-009dc000 rw-p 00000000 00:00 0 [heap]
7fbaf0000000-7fbaf0021000 rw-p 00000000 00:00 0
7fbaf0021000-7fbaf4000000 ---p 00000000 00:00 0
7fbaf4000000-7fbaf4021000 rw-p 00000000 00:00 0
7fbaf4021000-7fbaf8000000 ---p 00000000 00:00 0
7fbaf8000000-7fbaf8021000 rw-p 00000000 00:00 0
7fbaf8021000-7fbafc000000 ---p 00000000 00:00 0
7fbafc000000-7fbafc021000 rw-p 00000000 00:00 0
7fbafc021000-7fbb00000000 ---p 00000000 00:00 0
7fbb00000000-7fbb00021000 rw-p 00000000 00:00 0
7fbb00021000-7fbb04000000 ---p 00000000 00:00 0
7fbb0787e000-7fbb07893000 r-xp 00000000 ca:01 376 /lib64/libgcc_s-4.7.2-20121109.so.1
7fbb07893000-7fbb07a92000 ---p 00015000 ca:01 376 /lib64/libgcc_s-4.7.2-20121109.so.1
7fbb07a92000-7fbb07a93000 rw-p 00014000 ca:01 376 /lib64/libgcc_s-4.7.2-20121109.so.1
7fbb07a93000-7fbb07a9f000 r-xp 00000000 ca:01 4354 /lib64/libnss_files-2.12.so
7fbb07a9f000-7fbb07c9e000 ---p 0000c000 ca:01 4354 /lib64/libnss_files-2.12.so
7fbb07c9e000-7fbb07c9f000 r--p 0000b000 ca:01 4354 /lib64/libnss_files-2.12.so
7fbb07c9f000-7fbb07ca0000 rw-p 0000c000 ca:01 4354 /lib64/libnss_files-2.12.so
7fbb07ca0000-7fbb07ca1000 ---p 00000000 00:00 0
7fbb07ca1000-7fbb084a1000 rw-p 00000000 00:00 0 [stack:5552]
7fbb084a1000-7fbb084a2000 ---p 00000000 00:00 0
7fbb084a2000-7fbb08ca2000 rw-p 00000000 00:00 0 [stack:5551]
7fbb08ca2000-7fbb08ca3000 ---p 00000000 00:00 0
7fbb08ca3000-7fbb094a3000 rw-p 00000000 00:00 0 [stack:5550]
7fbb094a3000-7fbb094a4000 ---p 00000000 00:00 0
7fbb094a4000-7fbb09ca4000 rw-p 00000000 00:00 0 [stack:5549]
7fbb09ca4000-7fbb09ca5000 ---p 00000000 00:00 0
7fbb09ca5000-7fbb0a4a5000 rw-p 00000000 00:00 0 [stack:5548]
7fbb0a4a5000-7fbb0a4ac000 r-xp 00000000 ca:01 4366 /lib64/librt-2.12.so
7fbb0a4ac000-7fbb0a6ab000 ---p 00007000 ca:01 4366 /lib64/librt-2.12.so
7fbb0a6ab000-7fbb0a6ac000 r--p 00006000 ca:01 4366 /lib64/librt-2.12.so
7fbb0a6ac000-7fbb0a6ad000 rw-p 00007000 ca:01 4366 /lib64/librt-2.12.so
7fbb0a6ad000-7fbb0a82f000 r-xp 00000000 ca:01 4338 /lib64/libc-2.12.so
7fbb0a82f000-7fbb0aa2f000 ---p 00182000 ca:01 4338 /lib64/libc-2.12.so
7fbb0aa2f000-7fbb0aa33000 r--p 00182000 ca:01 4338 /lib64/libc-2.12.so
7fbb0aa33000-7fbb0aa34000 rw-p 00186000 ca:01 4338 /lib64/libc-2.12.so
7fbb0aa34000-7fbb0aa3a000 rw-p 00000000 00:00 0
7fbb0aa3a000-7fbb0aa51000 r-xp 00000000 ca:01 4362 /lib64/libpthread-2.12.so
7fbb0aa51000-7fbb0ac50000 ---p 00017000 ca:01 4362 /lib64/libpthread-2.12.so
7fbb0ac50000-7fbb0ac51000 r--p 00016000 ca:01 4362 /lib64/libpthread-2.12.so
7fbb0ac51000-7fbb0ac52000 rw-p 00017000 ca:01 4362 /lib64/libpthread-2.12.so
7fbb0ac52000-7fbb0ac56000 rw-p 00000000 00:00 0
7fbb0ac56000-7fbb0ac9a000 r-xp 00000000 ca:01 31036 /usr/lib64/libevent-2.0.so.5.1.6
7fbb0ac9a000-7fbb0ae9a000 ---p 00044000 ca:01 31036 /usr/lib64/libevent-2.0.so.5.1.6
7fbb0ae9a000-7fbb0ae9c000 rw-p 00044000 ca:01 31036 /usr/lib64/libevent-2.0.so.5.1.6
7fbb0ae9c000-7fbb0aeba000 r-xp 00000000 ca:01 3776 /lib64/ld-2.12.so
7fbb0b0af000-7fbb0b0b3000 rw-p 00000000 00:00 0
7fbb0b0b8000-7fbb0b0ba000 rw-p 00000000 00:00 0
7fbb0b0ba000-7fbb0b0bb000 r--p 0001e000 ca:01 3776 /lib64/ld-2.12.so
7fbb0b0bb000-7fbb0b0bc000 rw-p 0001f000 ca:01 3776 /lib64/ld-2.12.so
7fbb0b0bc000-7fbb0b0bd000 rw-p 00000000 00:00 0
7fffde61a000-7fffde63b000 rw-p 00000000 00:00 0 [stack]
7fffde6f1000-7fffde6f2000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Encountered using: Redis server version 2.4.17 (00000000:0) and Redis server v=2.8.3 sha=00000000:0 malloc=jemalloc-3.2.0 bits=64 build=5965a65f8c7ff3e
thanks, ac
@nicolasff I believe I am having the same issue using a similar example to the one provided in your README. I'm using webdis without deamonize mode if that helps.
Edit: I am also trying to do Pub/Sub commands over WebSockets.
Any updates on this?
@nicolasff Ping on this. Same issue today. Also Redis pub/sub.
Segfault after connecting a few times by web socket:
- thread #2, stop reason = EXC_BAD_ACCESS (code=1, address=0x0) frame #0: 0x0000000100015577 webdis`dictNext(iter=0x00000001007092e0) at dict.c:274 271 iter->index++; 272 if (iter->index >= 273 (signed)iter->ht->size) break; -> 274 iter->entry = iter->ht->table[iter->index]; 275 } else { 276 iter->entry = iter->nextEntry; 277 } (lldb) p iter (dictIterator *) $0 = 0x00000001007092e0 (lldb) p iter->ht (dict *) $1 = 0x000000010050da80 (lldb) p iter->ht->table (dictEntry **) $2 = 0x0000000000000000
That table pointer shouldn't be NULL, right?
Same issue on OS X
* thread #2, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
frame #0: 0x0000000100015527 webdis`dictNext(iter=0x0000000100700750) at dict.c:274
271 iter->index++;
272 if (iter->index >=
273 (signed)iter->ht->size) break;
-> 274 iter->entry = iter->ht->table[iter->index];
275 } else {
276 iter->entry = iter->nextEntry;
277 }
Target 0: (webdis) stopped.
(lldb) p iter->ht->table
(dictEntry **) $2 = 0x0000000000000000
(lldb) bt
warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available.
* thread #2, stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
* frame #0: 0x0000000100015527 webdis`dictNext(iter=0x0000000100700750) at dict.c:274
frame #1: 0x0000000100013ee0 webdis`__redisAsyncFree(ac=0x0000000101b00150) at async.c:291
frame #2: 0x0000000100014156 webdis`__redisAsyncDisconnect(ac=0x0000000101b00150) at async.c:348
frame #3: 0x00000001000140a8 webdis`redisAsyncDisconnect(ac=0x0000000101b00150) at async.c:361
frame #4: 0x0000000100008df0 webdis`pool_free_context(ac=0x0000000101b00150) at pool.c:32
frame #5: 0x0000000100000d3f webdis`cmd_free(c=0x000000010040b150) at cmd.c:52
frame #6: 0x0000000100007444 webdis`http_client_read(c=0x00000001007010a0) at client.c:298
frame #7: 0x0000000100001d37 webdis`worker_can_read(fd=151, event=2, p=0x00000001007010a0) at worker.c:45
frame #8: 0x00000001000ea43d libevent-2.1.6.dylib`event_process_active_single_queue + 574
frame #9: 0x00000001000e6f92 libevent-2.1.6.dylib`event_base_loop + 1171
frame #10: 0x0000000100002150 webdis`worker_main(p=0x0000000101800690) at worker.c:158
frame #11: 0x00007fff5dfc7661 libsystem_pthread.dylib`_pthread_body + 340
frame #12: 0x00007fff5dfc750d libsystem_pthread.dylib`_pthread_start + 377
frame #13: 0x00007fff5dfc6bf9 libsystem_pthread.dylib`thread_start + 13
Here is the first error valgrind reports on Linux:
=25858== Memcheck, a memory error detector
==25858== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==25858== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==25858== Command: ./webdis
==25858==
==25858== Thread 4:
==25858== Invalid read of size 4
==25858== at 0x11C42E: redisAsyncDisconnect (async.c:359)
==25858== by 0x112147: pool_free_context (pool.c:32)
==25858== by 0x10A832: cmd_free (cmd.c:52)
==25858== by 0x1109EF: http_client_read (client.c:298)
==25858== by 0x10B783: worker_can_read (worker.c:45)
==25858== by 0x4E5AA10: ??? (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.6.0.2)
==25858== by 0x4E5B33E: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.6.0.2)
==25858== by 0x10BC19: worker_main (worker.c:158)
==25858== by 0x50946DA: start_thread (pthread_create.c:463)
==25858== by 0x53CD88E: clone (clone.S:95)
==25858== Address 0x5721aa8 is 136 bytes inside a block of size 344 free'd
==25858== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25858== by 0x116A4C: redisFree (hiredis.c:633)
==25858== by 0x11C320: __redisAsyncFree (async.c:316)
==25858== by 0x11C412: __redisAsyncDisconnect (async.c:348)
==25858== by 0x11C46F: redisAsyncDisconnect (async.c:361)
==25858== by 0x1109A5: http_client_read (client.c:293)
==25858== by 0x10B783: worker_can_read (worker.c:45)
==25858== by 0x4E5AA10: ??? (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.6.0.2)
==25858== by 0x4E5B33E: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.6.0.2)
==25858== by 0x10BC19: worker_main (worker.c:158)
==25858== by 0x50946DA: start_thread (pthread_create.c:463)
==25858== by 0x53CD88E: clone (clone.S:95)
==25858== Block was alloc'd at
==25858== at 0x4C31D2F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==25858== by 0x11BBBF: redisAsyncInitialize (async.c:108)
==25858== by 0x11BD96: redisAsyncConnect (async.c:161)
==25858== by 0x1123FD: pool_connect (pool.c:129)
==25858== by 0x10B06B: cmd_run (cmd.c:224)
==25858== by 0x10BDCD: worker_process_client (worker.c:197)
==25858== by 0x110607: http_client_on_message_complete (client.c:203)
==25858== by 0x12906D: http_parser_execute (http_parser.c:1404)
==25858== by 0x110C37: http_client_execute (client.c:341)
==25858== by 0x10B81C: worker_can_read (worker.c:61)
==25858== by 0x4E5AA10: ??? (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.6.0.2)
==25858== by 0x4E5B33E: event_base_loop (in /usr/lib/x86_64-linux-gnu/libevent-2.1.so.6.0.2)
==25858==
The entire output is in this gist
I have worked around this issue by adding a little JS code which sends an UNSUBSCRIBE message before closing the window. Not very robust, but it works.
window.onbeforeunload = function() {
socket.send(JSON.stringify(["UNSUBSCRIBE", "channel"]));
return null;
};
Oh, I see you're doing the same thing. Maybe the difference is that I'm not using Jquery or that 4 years have passed and browsers have advanced. But without the window.onbeforeunload code webdis was crashing for me, also.
I'm sorry that this issue has been open for so long, but I am unfortunately unable to work on it at this time.
The websocket implementation was never fully tested and it's likely that there are serious issues with it, potentially including security risks. This is why it is currently disabled by default.
If by chance someone provides a patch for this bug I'd certainly be happy to review it and integrate it, but my involvement cannot currently go further than reviewing and merging pull requests.
Fair enough. But the issue is not isolated to websockets, it also occurs when using the recommend XmlHttpRequest communication.