[Libwebsockets] cpu > 96%

Andy Green andy at warmcat.com
Tue Jan 27 21:12:09 CET 2015



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




More information about the Libwebsockets mailing list