[Libwebsockets] cpu > 96%

Andy Green andy at warmcat.com
Wed Jan 28 15:30:38 CET 2015



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.

-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




More information about the Libwebsockets mailing list