[Libwebsockets] Double freeing causes crashing??

Duy Lan Nguyen ndlan2k at gmail.com
Fri Nov 6 09:51:29 CET 2015


Sorry, it was due to referring to already freed memory, not double freeing.
I can point to where it happens.
At line 300,
http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/tree/lib/client-handshake.c#n300,
wsi is freed by lws_free(wsi) (in function libwebsocket_client_connect_2,
called by lws_client_socket_service, called by libwebsocket_service_fd <=
lws_plat_service <= libwebsocket_service).
But that wsi memory is referred to again at
http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/tree/lib/lws-plat-win.c#n45
(in function wsi_from_fd, called by libwebsocket_context_destroy).

Do you think it is the problem? I can fix it by assigning wsi=NULL after
freeing and checking if wsi!=NULL before referring to its memory, then
git-pushing the change. Is that ok?

Besides, in the code as follows, I waited for the thread of
libwebsocket_service loop to stop before calling
libwebsocket_context_destroy(). So I think the crash may happen even
without threading.
if (pVeraSocket)
{
if (pVeraSocket->m_hThreadService && pVeraContext &&
pVeraContext->m_pVeraSocketInfo)
{
pVeraContext->m_pVeraSocketInfo->m_ConnInfo.m_fConnClosed = TRUE;

WaitForSingleObject(pVeraSocket->m_hThreadService, INFINITE);
CloseHandle(pVeraSocket->m_hThreadService);
pVeraSocket->m_hThreadService = NULL;
pVeraSocket->m_dwThreadServiceId = 0;
}
...
}

if (pVeraContext)
                {
s_rgppVeraSocketInfo[pVeraContext->m_nConnTicket] = NULL;
    if (pVeraContext->m_pContext)
{
libwebsocket_context_destroy(pVeraContext->m_pContext);
pVeraContext->m_pContext = NULL;
}
                }

I have a further question. I was trying to develop based on the following
description of libwebsocket_service() at
https://libwebsockets.org/libwebsockets-api-doc.html. If I don't interpret
it incorrectly, it means I could create another thread for the
libwebsocket_service() loop so that it doesn't block the main thread, which
can do other stuff. So how should I interpret this description?
"*int* *libwebsocket_service* (*struct libwebsocket_context ** *context*,
*int* *timeout_ms*)
...Description

This function deals with any pending websocket traffic, for three kinds of
event. It handles these events on both server and client types of
connection the same.

1) Accept new connections to our context's server

2) Call the receive callback for incoming frame data received by server or
client connections.

You need to call this service function periodically to all the above
functions to happen; if your application is single-threaded you can just
call it in your main event loop.

Alternatively you can fork a new process that asynchronously handles
calling this service in a loop. In that case you are happy if this call
blocks your thread until it needs to take care of something and would call
it with a large nonzero timeout. Your loop then takes no CPU while there is
nothing happening.

If you are calling it in a single-threaded app, you don't want it to wait
around blocking other things in your loop from happening, so you would call
it with a timeout_ms of 0, so it returns immediately if nothing is pending,
or as soon as it services whatever was pending."

Thanks,
Lan



On Wed, Nov 4, 2015 at 7:16 PM, Andy Green <andy at warmcat.com> wrote:

>
>
> On 5 November 2015 09:52:11 GMT+08:00, Duy Lan Nguyen <ndlan2k at gmail.com>
> wrote:
> >Hi Andy and Anyone-who-can-help,
> >
> >We have a situation of double freeing and crashing here and wonder if
> >anyone can help.
>
> Maybe someone else can help.
>
> I don't have windows, and lws doesn't have threads.
>
> If you can make a patch that does the minimum to lws-test-server to make
> the problem come on Linux, I'll study it.  But the answer is likely in your
> threading additions outside of lws.
>
> -Andy
>
> >We use lws as follows, with highlights
> >
> >We have a connection function VeraConnect that calls
> >libwebsocket_create_context and libwebsocket_client_connect, and
> >creates
> >another thread PollService for the polling service
> >libwebsocket_service. If
> >VeraConnect fails, it will clean up by stopping the thread PollService
> >and
> >calling libwebsocket_context_destroy. The functions VeraConnect and
> >PollService are summarized as below.
> >
> >...
> >VeraConnect(...)
> >{
> >....
> >  if (!pVeraContext->m_pContext)
> >    {
> >        pVeraContext->m_pContext = libwebsocket_create_context
> >(pVeraContext->m_pInfo);
> >        if (!pVeraContext->m_pContext) {
> >            ret = VERA_FAIL;
> >            goto exit;
> >        }
> >    }
> >
> >pVeraSocket->m_pWSI =
> >libwebsocket_client_connect(pVeraContext->m_pContext,
> >...);
> >
> >    if (!pVeraSocket->m_pWSI) {
> >        ret = VERA_FAIL;
> >        goto exit;
> >    }
> >
> >  pVeraContext->m_pVeraSocketInfo->m_ConnInfo.m_fConnClosed = FALSE;
> >
> >  pVeraSocket->m_hThreadService = CreateThread(
> >...
> >        PollService,       // thread function name
> >        pVeraContext,          // argument to thread function
> >...);   // returns the thread identifier
> >
> >exit:
> >  if (ret != VERA_OK)
> >    {
> >if (pVeraSocket)
> >{
> >if (pVeraSocket->m_hThreadService && pVeraContext &&
> >pVeraContext->m_pVeraSocketInfo)
> >{
> >pVeraContext->m_pVeraSocketInfo->m_ConnInfo.m_fConnClosed = TRUE;
> >
> >WaitForSingleObject(pVeraSocket->m_hThreadService, INFINITE);
> >CloseHandle(pVeraSocket->m_hThreadService);
> >pVeraSocket->m_hThreadService = NULL;
> >pVeraSocket->m_dwThreadServiceId = 0;
> >}
> >...
> >}
> >
> >if (pVeraContext)
> >                {
> >s_rgppVeraSocketInfo[pVeraContext->m_nConnTicket] = NULL;
> >    if (pVeraContext->m_pContext)
> >{
> >libwebsocket_context_destroy(pVeraContext->m_pContext);
> >pVeraContext->m_pContext = NULL;
> >}
> >                }
> >...
> >   }
> >...
> >}
> >...
> >... PollService(LPVOID lpParam)
> >{
> >        int n = 0;
> >VeraContext *pVeraContext = (VeraContext *)lpParam;
> >
> >if (pVeraContext && pVeraContext->m_pVeraSocketInfo &&
> >pVeraContext->m_pContext)
> >{
> >BOOL *pfSocketClosed =
> >&pVeraContext->m_pVeraSocketInfo->m_ConnInfo.m_fConnClosed;
> >struct libwebsocket_context *pContext = pVeraContext->m_pContext;
> >
> >while (n >= 0 && !*pfSocketClosed) {
> >n = libwebsocket_service(pContext, 64);
> >}
> >}
> >        return 0;
> >}
> >
> >Sometimes, our first VeraConnect call fails, then the immediate next
> >VeraConnect call crashes. The crash details are below, with line
> >numbers (e.g.
> >one line below refers to calling wsi_from_fd() near line 310 of
> >context.c
> >in function libwebsocket_context_destroy()). Basically, the memory has
> >been
> >freed by libwebsocket_service below (its trace includes
> >libwebsocket_service_fd, lws_client_socket_service,
> >libwebsocket_client_connect_2, _realloc), but it is then freed again by
> >the
> >libwebsocket_context_destroy() inside VeraConnect. Therefore it
> >crashes.
> >
> >So could anyone please tell me if my way of using lws should be changed
> >to
> >fix this? Or is there a way to change lws to avoid this crash?
> >
> >Many thanks,
> >Lan
> >
> >original faulting stack:
> >
> >0:003> .ecxr
> >rax=000000000477cee0 rbx=0000000013f70c50 rcx=0000000000000000
> >rdx=000000000402d680 rsi=0000000000000000 rdi=0000000000000000
> >rip=00000000ff3f159a rsp=000000000659f788 rbp=00000000ff406ba0
> > r8=0000000000000004  r9=0000000013f70c50 r10=0000000000000280
> >r11=0000000000000004 r12=0000000000000000 r13=0000000000000102
> >r14=000000000659f880 r15=0000000004847ff8
> >iopl=0         nv up ei pl nz na pe nc
> >cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b
> >efl=00010202
> >phantom!wsi_from_fd+0x3a:
> >00000000`ff3f159a 44395060        cmp     dword ptr [rax+60h],r10d
> >ds:00000000`0477cf40=????????
> >0:003> kv
> >  *** Stack trace for last set context - .thread/.cxr resets it
> >Child-SP          RetAddr           : Args to
> >Child                                                           : Call
> >Site
> >00000000`0659f788 00000000`ff3efe1f : 00000000`00000000
> >00000000`ff3a1c74
> >00000000`ff3a1c78 00000000`03eade30 : phantom!wsi_from_fd+0x3a
> >[c:\libwebsockets\lib\lws-plat-win.c @ 45]
> >00000000`0659f790 00000000`ff3c2b7f : 00000000`00000102
> >00000000`03eade30
> >00000000`03eade20 00000000`04847fe0 :
> >phantom!libwebsocket_context_destroy+0x5f
> >[c:\libwebsockets\lib\context.c @ 310]
> >00000000`0659f7d0 00000000`ff3bec11 : 00000000`0659f898
> >00000000`02460000
> >00000000`00000050 00000000`ff40e5f8 : phantom!VeraConnect+0x29f
> >[c:\socketcode\c\verasock\verasocklws.c @ 1194]
> >...
> >00000000`0659ff10 00000000`76fa3281 : 00000000`00000000
> >00000000`00000000
> >00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd
> >00000000`0659ff40 00000000`00000000 : 00000000`00000000
> >00000000`00000000
> >00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d
> >
> >0:003> !heap -p -a 000000000477cee0
> >    address 000000000477cee0 found in
> >    _DPH_HEAP_ROOT @ 3d51000
> >    in free-ed allocation (  DPH_HEAP_BLOCK:         VirtAddr
> >VirtSize)
> >                                    3d549c0:          477c000
> >2000
> >*** ERROR: Symbol file could not be found.  Defaulted to export symbols
> >for
> >verifier.dll -
> >    000007fef45b8726
> >verifier!VerifierDisableFaultInjectionExclusionRange+0x000000000000234e
> >    000000007703c415 ntdll!RtlDebugFreeHeap+0x0000000000000035
> >    0000000076fdd0fe ntdll! ?? ::FNODOBFM::`string'+0x00000000000122e2
> >    0000000076fc2075 ntdll!RtlFreeHeap+0x00000000000001a2
> >*** ERROR: Symbol file could not be found.  Defaulted to export symbols
> >for
> >msvcrt.dll -
> >    000007fefd4e10c4 msvcrt!free+0x000000000000001c
> >    00000000ff3f2bac phantom!_realloc+0x000000000000001c
> >[c:\libwebsockets\lib\alloc.c @ 9]
> >00000000ff3f0e77
> >phantom!libwebsocket_client_connect_2+0x00000000000003b7
> >[c:\libwebsockets\lib\client-handshake.c @ 289]
> >  00000000ff3f5385 phantom!lws_client_socket_service+0x0000000000000045
> >[c:\libwebsockets\lib\client.c @ 63]
> >    00000000ff3f0a46 phantom!libwebsocket_service_fd+0x00000000000003f6
> >[c:\libwebsockets\lib\service.c @ 616]
> >    00000000ff3f1909 phantom!lws_plat_service+0x0000000000000119
> >[c:\libwebsockets\lib\lws-plat-win.c @ 164]
> >    00000000ff3c1cf6 phantom!PollService+0x0000000000000036
> >[c:\socketcode\c\verasock\verasocklws.c @ 377]
> >    0000000076e6f56d kernel32!BaseThreadInitThunk+0x000000000000000d
> >    0000000076fa3281 ntdll!RtlUserThreadStart+0x000000000000001d
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://libwebsockets.org/pipermail/libwebsockets/attachments/20151106/42bb4de5/attachment-0001.html>


More information about the Libwebsockets mailing list