[Libwebsockets] cpu > 96%

Gesiel gesielmm at gmail.com
Thu Jan 29 12:32:25 CET 2015


On 28/01/2015 22:45, Andy Green wrote:
>
> On 28 January 2015 22:30:38 GMT+08:00, Andy Green <andy at warmcat.com> wrote:
>>
>> On 28 January 2015 21:29:49 GMT+08:00, Andy Green <andy at warmcat.com>
>> wrote:
>>>
>>> On 28 January 2015 20:57:26 GMT+08:00, Gesiel <gesielmm at gmail.com>
>>> wrote:
>>>> Hi,
>>>>
>>>> Compiled without SSL support (-DLWS_WITH_SSL = 0)
>>>> and the CPU is not longer tied when called
>>>> libwebsocket_cancel_service()
>>> >from another thread (Actually not even have to be from another
>> thread,
>>>> calling on the main thread already has the problem).
>>>> I suspect the problem is in the lws-plat-unix.c file when compiling
>>>> with -DLWS_WITH_SSL = 1, lws_plat_service function() on line 111:
>>>>
>>>> #ifdef LWS_OPENSSL_SUPPORT
>>>>      / * If we know we have non-network pending date, do not wait in
>>>> poll * /
>>>>      if (context-> ssl_flag_buffered_reads)
>>>>          timeout_ms = 0;
>>>> #endif
>>>>
>>>> I believe that somehow the timeout is being reset before reaching the
>>>> poll() function
>>>> when compiled with OPENSSL _SUPPORT and invoking
>>>> libwebsocket_cancel_service ().
>>> Yes it makes sense I think... it's a latency optimization that works
>>> fine if someone wanted some service because it'll get priority.
>>>
>>> But if nobody "real" (just the interruption pipe) wanted service,
>>> setting the poll timeout to 0 which is the optimization trick that
>> will
>>> exactly make you busyloop until someone wanted service.
>>>
>>> And he doesn't know we did a standalone pipe action.... hum let me
>>> stare at it a bit.
>> I can see a good way forward, I'll continue with it tomorrow.
> I pushed a couple of patches that improve how buffered ssl reads are managed that should remove this problem as a side effect (if it works properly), please give current HEAD a try.
>
> -Andy
>
>> -Andy
>>
>>> -Andy
>>>
>>>> Thanks
>>>>
>>>>
>>>> On 27/01/2015 17:12, Andy Green wrote:
>>>>> On 28 January 2015 02:27:32 GMT+08:00, Gesiel <gesielmm at gmail.com>
>>>> wrote:
>>>>>> First thanks for the library.
>>>>>> I noticed that after a call libwebsocket_cancel_service in another
>>>>>> thread, the CPU rises above 96%.
>>>>>> I tested also calling
>>> libwebsocket_callback_on_writable_all_protocol
>>>>>> that same thread, showing the same thing.
>>>>>> This thread is simply by setting one flag (ws_flags_write_all) for
>>>> the
>>>>>> main thread calls libwebsocket_callback_on_writable_all_protocol.
>>>>>> The problem presents itself when enters 'y' via keyboard on which
>>>> sets
>>>>>> the flag and calls libwebsocket_cancel_service.
>>>>>> In this thread I can get around this by setting the flag and just
>>>> never
>>>>>> calling libwebsocket_cancel_service or
>>>>>> libwebsocket_callback_on_writable_all_protocol,
>>>>>> using a small timeout in libwebsocket_service.
>>>>>> It is curious because libwebsocket_cancel_service just write the
>>>> dummy
>>>>>> pipe while libwebsocket_callback_on_writable_all_protocol do more
>>>>>> things.
>>>>> Usually the way to debug busywaiting is find out where he's
>> spinning
>>>> and then why he feels he should spin.
>>>>> Normally the answer with threads is 'you can't call that from
>>> another
>>>> thread' but in this case, it's meant to be threadsafe.  So I guess
>> the
>>>> problem is when you call writeable api, he triggers the pipe AND
>>>> somebody needs service.  Maybe trigger the pipe but nobody else has
>>>> POLLx on their fd has a bug.
>>>>> So stick some logging in the platform service routine and see what
>>>> the flow is like in there when you start spinning.
>>>>> -Andy
>>>>>
>>>>>> I'm running on the raspberry pi model b.
>>>>>>
>>>>>> My Thread:
>>>>>>
>>>> ------------------------------------------------------------------------------------
>>>>>> static volatile int ws_flags_write_all = 0;
>>>>>>
>>>>>> static void * my_thread(void *arg){
>>>>>>       char buf[25];
>>>>>>
>>>>>>       while(!force_exit) {
>>>>>>
>>>>>>           printf("\n>>>");
>>>>>>           fflush(stdout);
>>>>>>
>>>>>>           if(fgets(buf, 20, stdin)==NULL)
>>>>>>               continue;
>>>>>>
>>>>>>           if(buf[0] == 'q' || buf[0] == 'Q'){
>>>>>>               force_exit = 1;
>>>>>>               libwebsocket_cancel_service(context);
>>>>>>               break;
>>>>>>           }
>>>>>>
>>>>>>           switch(buf[0]){
>>>>>>               case 'x': ws_flags_write_all = 1; break;  /* continue
>>>> dumb
>>>>>> protocol, cpu OK  */
>>>>>>               case 'X': ws_flags_write_all = 0; break;  /* pause
>>> dumb
>>>>>> protocol, cpu OK     */
>>>>>>              case 'y':                                  /* continue
>>>> dumb
>>>>>> protocol cpu > 96% !!!! */
>>>>>>                   ws_flags_write_all = 1;
>>>>>>                   libwebsocket_cancel_service(context);
>>>>>>           }
>>>>>>       }
>>>>>>
>>>>>>       return NULL;
>>>>>> }
>>>>>>
>>>>>>
>>>> -------------------------------------------------------------------------------------
>>>>>> Part Main thread:
>>>>>>
>>>>>>           pthread_t thr;
>>>>>>           if((n = pthread_create(&thr, NULL, &my_thread, NULL)) !=
>>>> 0){
>>>>>>               errno = n;
>>>>>>               perror("pthread_create");
>>>>>>               return -1;
>>>>>>           }
>>>>>>
>>>>>>           n = 0;
>>>>>>           while (n >= 0 && !force_exit) {
>>>>>>                   struct timeval tv;
>>>>>>
>>>>>>                   gettimeofday(&tv, NULL);
>>>>>>
>>>>>>                   /*
>>>>>>                    * This provokes the
>> LWS_CALLBACK_SERVER_WRITEABLE
>>>> for
>>>>>> every
>>>>>>                    * live websocket connection using the
>>>> DUMB_INCREMENT
>>>>>> protocol,
>>>>>>                    * as soon as it can take more packets (usually
>>>>>> immediately)
>>>>>>                    */
>>>>>>                   if(ws_flags_write_all){  /* set only in my_thread
>>>> */
>>>>>>                       ms = (tv.tv_sec * 1000) + (tv.tv_usec /
>> 1000);
>>>>>>                       if ((ms - oldms) > 50) {
>>>>>>
>>>> libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_DUMB_INCREMENT]);
>>>>>>                           oldms = ms;
>>>>>>                       }
>>>>>>                   }
>>>>>> #ifdef EXTERNAL_POLL
>>>>>>
>>>>>>                   /*
>>>>>>                * this represents an existing server's single poll
>>>> action
>>>>>>                    * which also includes libwebsocket sockets
>>>>>>                    */
>>>>>>
>>>>>>                   n = poll(pollfds, count_pollfds, 50);
>>>>>>                   if (n < 0)
>>>>>>                           continue;
>>>>>>
>>>>>>
>>>>>>                   if (n)
>>>>>>                           for (n = 0; n < count_pollfds; n++)
>>>>>>                                   if (pollfds[n].revents)
>>>>>>                                           /*
>>>>>>                                          * returns immediately if
>>> the
>>>> fd
>>>>>> does not
>>>>>>                                           * match anything under
>>>>>> libwebsockets
>>>>>>                                           * control
>>>>>>                                           */
>>>>>>                                           if
>>>>>> (libwebsocket_service_fd(context,
>>>>>> &pollfds[n]) < 0)
>>>>>>                                                   goto done;
>>>>>> #else
>>>>>>                   /*
>>>>>>                    * If libwebsockets sockets are all we care
>> about,
>>>>>>                    * you can use this api which takes care of the
>>>> poll()
>>>>>>                    * and looping through finding who needed
>> service.
>>>>>>                    *
>>>>>>                  * If no socket needs service, it'll return anyway
>>>> after
>>>>>>                    * the number of ms in the second argument.
>>>>>>                    */
>>>>>>
>>>>>>                   n = libwebsocket_service(context, 50);
>>>>>> #endif
>>>>>>           }
>>>>>>
>>>>>> #ifdef EXTERNAL_POLL
>>>>>> done:
>>>>>> #endif
>>>>>>
>>>>>>           libwebsocket_context_destroy(context);
>>>>>>
>>>>>>           lwsl_notice("libwebsockets-test-server exited
>> cleanly\n");
>>>>>> #ifndef WIN32
>>>>>>           closelog();
>>>>>> #endif
>>>>>>
>>>>>>           pthread_cancel(thr);
>>>>>>           pthread_join(thr, NULL);
>>>>>>
>>>>>>           return 0;
>>>>>>
>>>> --------------------------------------------------------------------------------------
>>>>>> Console output:
>>>>>>
>>>>>> lwsts [31255]: libwebsockets test server - (C) Copyright 2010-2014
>>>> Andy
>>>>>> Green <andy at warmcat.com> - licensed under LGPL2.1
>>>>>> Using resource path "/home/pi/test-server"
>>>>>> lwsts [31255]: Initial logging level 7
>>>>>> lwsts [31255]: Library version: 1.3 080e6dd
>>>>>> lwsts [31255]: IPV6 not compiled in
>>>>>> lwsts [31255]: libev support not compiled in
>>>>>> lwsts [31255]: static allocation: 4480 + (12 x 1024 fds) = 16768
>>>> bytes
>>>>>> lwsts [31255]: canonical_hostname raspberrypi
>>>>>> lwsts [31255]: per-conn Memory: 144 + 2100 + protocol headers rx
>>> buf
>>>>>> lwsts [31255]: Compiled with OpenSSL support
>>>>>> lwsts [31255]: Using non-SSL mode
>>>>>> lwsts [31255]: Listening on port 7681
>>>>>>
>>>>>>
>>>>>> Modified file test-server.c
>>>>>> http://pastebin.com/DMah3jNc
>>>>>>
>>>>>>
>>>>>> Thank U
>>>>>>
>>>>>> ---
>>>>>> Este email foi escaneado pelo Avast antivírus.
>>>>>> http://www.avast.com
>>>>
>>>> ---
>>>> Este email foi escaneado pelo Avast antivírus.
>>>> http://www.avast.com
>>> _______________________________________________
>>> Libwebsockets mailing list
>>> Libwebsockets at ml.libwebsockets.org
>>> http://ml.libwebsockets.org/mailman/listinfo/libwebsockets
>> _______________________________________________
>> Libwebsockets mailing list
>> Libwebsockets at ml.libwebsockets.org
>> http://ml.libwebsockets.org/mailman/listinfo/libwebsockets
Hi,
It worked like a charm !!!
tested the test-server with --ssl parameter and also without the parameter.
Now you can cancel the service from another thread safely.
Congratulations !!!

Thanks

---
Este email foi escaneado pelo Avast antivírus.
http://www.avast.com




More information about the Libwebsockets mailing list