[Libwebsockets] cpu > 96%

Gesiel gesielmm at gmail.com
Wed Jan 28 13:57:26 CET 2015


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 ().

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