[Libwebsockets] Segfault

Jack Mitchell ml at communistcode.co.uk
Tue Jan 29 13:46:09 CET 2013


On 29/01/13 11:44, "Andy Green (林安廸)" wrote:
> On 29/01/13 19:31, the mail apparently from Jack Mitchell included:
>> On 29/01/13 11:20, "Andy Green (林安廸)" wrote:
>>> On 29/01/13 19:12, the mail apparently from Jack Mitchell included:
>>>>
>>>>> No worries, I am wondering if the broadcast and forked service stuff
>>>>> is leading people down the wrong path at the moment and should get
>>>>> removed, so it will be interesting to see how you go.
>>>>>
>>>>> -Andy
>>>>
>>>> Sorry to snip this short but I couldn't cope with all the 
>>>> indentation..
>>>>
>>>> I have now implemented a ring buffer but something odd is happening.
>>>> With 1 page open it performs fine, however when I open an additional
>>>> page only some of the data makes it through the socket? I check for a
>>>
>>> It seems that when you send data to one websocket client, you mark it
>>> at that time "done" from your ringbuffer?  Actually it's only
>>> "consumed" when you sent it to everybody who cares.
>>>
>>> -Andy
>>
>> Should libwebsocket_callback_on_writable_all_protocol() not give me a
>> callback with a wsi that writes to all the clients of that protocol as I
>
> Sort of...
>
>> did with broadcast()? Or am I missing something fundamental, where I
>> need to loop over each wsi and write them individually somehow?
>
> No you don't hae to do anything extra about that.
>
> The point is that different connections may become writeable at 
> grossly different rates.  Consider one guy is connecting through a 3G 
> phone, his connection may disappear and reappear over several 
> seconds.  He's not going to become writeable (and get that callback 
> with his wsi) while he's in a tunnel or whatever and you already 
> filled his pipe; he's not emptying his pipe at that time. It sounds 
> like you're thinking of these connections as perfect data sinks and 
> they are not at all.
>
> Instead what that call is doing is promising to give you a call back 
> for each wsi of that protocol "when they can take some more".  So for 
> the tunnel guy, his callback will come when he has come out of the 
> tunnel and received and acknowledged the first packet in his pipe.  
> Other connections to other peers will of course have been chugging 
> along taking data the whole time.
>
> So, you need a policy for how long you will buffer content in your 
> ringbuffer before the remote client won't "catch up" any more if it 
> stopped receiving for a while, and you need to only retire ringbuffer 
> entries that have gone to all consumers you are willing to send to.

Ok, I've got it sorted [1]. The client gets 50ms to respond otherwise 
they miss the data. Is there a way to check if all clients have 
responded, or if all the clients pipes are empty?

[1]

while(1)

       usleep(50000);

       /* Service the websocket here to listen for connection attempts */
       libwebsocket_service(controlWebSocket, 0);

       for (i = 0; i < NUM_TOTAL_CARDS; i++)
       {

          if (card[i]->status == CARD_AVAILABLE)
          {

             libwebsocket_service(card[i]->websocketContext, 0);

             if (!ringBuffer_isEmpty(card[i]))
             {

                libwebsocket_callback_on_writable_all_protocol(
&card[i]->webSocketProtocol[PROTOCOL_SEND_RECIEVE]);

                ringBuffer_consume(card[i]->position);

             }

          }

}

>
> The approach the test server takes is when the ringbuffer has filled 
> up, to free up the entry that would be overwritten by the next 
> incoming one.
>
> -Andy
>
>>>> choked socket in my LWS_CALLBACK_SERVER_WRITEABLE case but it never
>>>> flags so I don't think it is a choked socket. Do you have any ideas?
>>>>
>>>> So the first page continues to work as expected, the second page only
>>>> receives snippets of data. My code is similar to the following:
>>>>
>>>> Polling loop:
>>>>
>>>> while (1)
>>>>      {
>>>>
>>>>          usleep(50000);
>>>>
>>>>          libwebsocket_service(websocketContext, 0);
>>>>
>>>>           if (!ringBuffer_isEmpty(buff)
>>>>          {
>>>>
>>>>          libwebsocket_callback_on_writable_all_protocol(
>>>>             webSocketProtocol[PROTOCOL_SEND_RECIEVE]);
>>>>
>>>>          }
>>>>      }
>>>>
>>>> LWS_CALLBACK
>>>>
>>>>        case LWS_CALLBACK_SERVER_WRITEABLE:
>>>>
>>>>           do {
>>>>
>>>>              if (lws_send_pipe_choked(wsi))
>>>>              {
>>>>
>>>>                 printf("Pipe was choked, giving it some breathing
>>>> space!\n");
>>>>                 break;
>>>>
>>>>              }
>>>>
>>>>              allConsumed = ringBuffer_consume(psd_sr->buff, 
>>>> jsonString);
>>>>
>>>>              n = sprintf((char*)p, "%s", jsonString);
>>>>
>>>>              n = libwebsocket_write(wsi, p, n, LWS_WRITE_TEXT);
>>>>
>>>>              if (n < 0)
>>>>              {
>>>>
>>>>                 handleError(DB_ERR_SOCKET,"Failed to write to socket!
>>>> (LWS_CALLBACK_SERVER_WRITEABLE)", __FUNCTION__);
>>>>                 return 1;
>>>>
>>>>              }
>>>>
>>>>           } while ( allConsumed != 1 );
>>>>
>>>>           break;
>>>>
>>>> Cheers,
>>>>
>>>
>>
>>
>


-- 

   Jack Mitchell (jack at embed.me.uk)
   Embedded Systems Engineer
   http://www.embed.me.uk

--




More information about the Libwebsockets mailing list