[Libwebsockets] cpu > 96%

Andy Green andy at warmcat.com
Wed Jan 28 14:29:49 CET 2015



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.

-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




More information about the Libwebsockets mailing list