<div dir="ltr"><div class="im" style="font-family:arial,sans-serif;font-size:13px"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

It's better not to use pthread_self but the api that gives the int thread id, since we store it in an int</blockquote></div><div style="font-family:arial,sans-serif;font-size:13px">I do not have access to  <span style="font-family:monospace;white-space:pre-wrap"><font color="#000000">pthread_getthreadid_np() or any other api the int thread id (I found this explaination here: </font></span><a href="http://stackoverflow.com/questions/19954890/why-compiler-says-pthread-getthreadid-np-was-not-declared-in-this-scope" target="_blank">http://stackoverflow.com/questions/19954890/why-compiler-says-pthread-getthreadid-np-was-not-declared-in-this-scope</a>)<br>

</div><div class="im" style="font-family:arial,sans-serif;font-size:13px"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

You can test the ppoll side by just making it wait in ppoll for a long time and use kill to fire a sigusr2 at it from another terminal and confirm the ppoll exits.</blockquote></div><div style="font-family:arial,sans-serif;font-size:13px">

ppoll in libwebsocket_service() doesn't exit using kill -SIGUSR2 PID. I also tried to change poll by ppoll in test-server.c with #define EXTERNAL_POLL (by the way, it would be better to integrate everything within #ifdef EXTERNAL_POLL as we need already to do so when using threading)  :</div>

<div style="font-family:arial,sans-serif;font-size:13px"><br></div><div style="font-family:arial,sans-serif;font-size:13px"><div>static void lws_sigusr2(int sig)</div><div>{</div><div>}</div></div><div class="im" style="font-family:arial,sans-serif;font-size:13px">

<div>int main(int argc, char **argv)<br></div><div>{</div></div><blockquote style="font-family:arial,sans-serif;font-size:13px;margin:0px 0px 0px 40px;border:none;padding:0px"><div>(...)</div><div>signal(SIGUSR2, lws_sigusr2);</div>

<div class="im">while (n >= 0 && !force_exit) {</div><div>#ifdef EXTERNAL_POLL</div><div class="im"><div><br></div><div><span style="white-space:pre-wrap">                </span>/*</div><div><span style="white-space:pre-wrap">               </span> * this represents an existing server's single poll action</div>

<div><span style="white-space:pre-wrap">          </span> * which also includes libwebsocket sockets</div><div><span style="white-space:pre-wrap">             </span> */</div></div><div><span style="white-space:pre-wrap">         </span>struct timespec timeout_ts;</div>

<div><span style="white-space:pre-wrap">                  </span>sigset_t sigmask;</div><div><br></div><div><span style="white-space:pre-wrap">               </span>timeout_ts.tv_sec = 60;</div><div><span style="white-space:pre-wrap">          </span>timeout_ts.tv_nsec = 0;</div>

<div><span style="white-space:pre-wrap">          </span>sigemptyset(&sigmask);</div><div><span style="white-space:pre-wrap">               </span>sigaddset(&sigmask, SIGUSR2);</div><div><br></div><div><span style="white-space:pre-wrap">               </span>/* wait for something to need service */</div>

<div><br></div><div><span style="white-space:pre-wrap">         </span>//n = poll(pollfds, count_pollfds, 50);</div><div><span style="white-space:pre-wrap">          </span>n = ppoll(pollfds, count_pollfds, &timeout_ts, &sigmask);</div>

<div><span style="white-space:pre-wrap">          </span>printf("here\n");</div><div>    (...)</div><div>}</div></blockquote><span style="font-family:arial,sans-serif;font-size:13px">(...)</span><br style="font-family:arial,sans-serif;font-size:13px">

<div style="font-family:arial,sans-serif;font-size:13px">}</div><div style="font-family:arial,sans-serif;font-size:13px">But it keeps blocking for 60 s... There must be somthing wrong for ppoll but here I am doing the test on a standard Ubuntu distribution.</div>

<div class="im" style="font-family:arial,sans-serif;font-size:13px"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

Testing the whole thing needs the main ws protocol connection to be connected and idle until the other thread provokes it to do something.</blockquote></div><div style="font-family:arial,sans-serif;font-size:13px">Why my simple thread created in test-server.c cannot be used as a simple test?</div>

<div style="font-family:arial,sans-serif;font-size:13px"><br></div><div style="font-family:arial,sans-serif;font-size:13px"><div>void *asynchronousSending(void *arg) {</div><div class="im"><div><br></div><div><span style="white-space:pre-wrap">    </span>printf("START asynchronous sending\n");</div>

</div><div><span style="white-space:pre-wrap">      </span>printf("Thread PID : %d\n",getpid());</div><div><span style="white-space:pre-wrap">  </span>printf("asynchronousSending pthread_self():%d\n",(unsigned int)pthread_self());</div>

<div><br></div><div><span style="white-space:pre-wrap"> </span>struct libwebsocket_context *context = (struct libwebsocket_context *) arg;</div><div><br></div><div><span style="white-space:pre-wrap">     </span>while (1) {</div>

<div><br></div><div><span style="white-space:pre-wrap">         </span>int i = 0;</div><div><span style="white-space:pre-wrap">               </span>for (i = 0; i < NB_CLIENTS; i++) {</div><div><span style="white-space:pre-wrap">                    </span>if (wsiForThread[i] != NULL ) {</div>

<div><br></div><div><span style="white-space:pre-wrap">                         </span>libwebsocket_callback_on_writable(context, wsiForThread[i]);</div><div><span style="white-space:pre-wrap">     </span>//<span style="white-space:pre-wrap">                      </span>raise(SIGUSR2);</div>

<div><span style="white-space:pre-wrap">                  </span>}</div><div><span style="white-space:pre-wrap">                </span>}</div><div><span style="white-space:pre-wrap">                </span>usleep(10000);</div></div></div><div class="gmail_extra"><br>

<br><div class="gmail_quote">2014/1/3 Andy Green <span dir="ltr"><<a href="mailto:andy@warmcat.com" target="_blank">andy@warmcat.com</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div class="im"><br>
<br>
Thomas Spitz <<a href="mailto:thomas.spitz@hestia-france.com">thomas.spitz@hestia-france.com</a>> wrote:<br>
>Hello Andy,<br>
><br>
</div><div class="im">>It doesn't seem to work.<br>
><br>
>In order to debug, I added the following printf in libwebsockets.c<br>
>#ifdef LWS_HAS_PPOLL<br>
>/*<br>
> * if we changed something in this pollfd...<br>
> *   ... and we're running in a different thread context<br>
> *     than the service thread...<br>
> *       ... and the service thread is waiting in ppoll()...<br>
> *          then fire a SIGUSR2 at the service thread to force it to<br>
> *             restart the ppoll() with our changed events<br>
> */<br>
>if (events != context->fds[wsi->position_in_fds_table].events) {<br>
> sampled_ppoll_tid = lws_idling_ppoll_tid;<br>
</div>>*printf("sampled_ppoll_tid: %d\n",sampled_ppoll_tid);*<br>
<div class="im">> if (sampled_ppoll_tid) {<br>
>tid = context->protocols[0].callback(context, NULL,<br>
>     LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);<br>
> if (tid != sampled_ppoll_tid)<br>
</div>>*printf("kill(sampled_ppoll_tid, SIGUSR2)\n");*<br>
<div><div class="h5">>kill(sampled_ppoll_tid, SIGUSR2);<br>
> }<br>
>}<br>
>#endif<br>
><br>
>Here below is the log I get when opening test.html while test-server.c<br>
>is<br>
>running (Enclosed my modified test-server.c with a asynchronous sending<br>
>thread). Counter is increased to 1 and then 1 minute elapsed before it<br>
>is<br>
>increased to 2.<br>
><br>
>webserver PID : 24290<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>START asynchronous sending<br>
>Thread PID : 24290<br>
>asynchronousSending pthread_self():-1678948608<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>    GET URI = /<br>
>    Host = <a href="http://192.168.1.6:7681" target="_blank">192.168.1.6:7681</a><br>
>    Connection = keep-alive<br>
>    Accept: =<br>
>text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8<br>
>    Accept-Encoding: = gzip,deflate,sdch<br>
>    Accept-Language: = fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4<br>
>    Cache-Control: = max-age=0<br>
>    Cookie: = test=LWS_1388753472_194286_COOKIE<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>sampled_ppoll_tid: -1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1678948608<br>
>kill(sampled_ppoll_tid, SIGUSR2)<br>
>    GET URI = /libwebsockets.org-logo.png<br>
>    Host = <a href="http://192.168.1.6:7681" target="_blank">192.168.1.6:7681</a><br>
>    Connection = keep-alive<br>
>    Accept: = image/webp,*/*;q=0.8<br>
>    Accept-Encoding: = gzip,deflate,sdch<br>
>    Accept-Language: = fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4<br>
>    Cache-Control: = max-age=0<br>
>    Cookie: = test=LWS_1388753472_194286_COOKIE<br>
>    Referer: = <a href="https://192.168.1.6:7681/" target="_blank">https://192.168.1.6:7681/</a><br>
>    GET URI = /xxx<br>
>    Host = <a href="http://192.168.1.6:7681" target="_blank">192.168.1.6:7681</a><br>
>    Connection = Upgrade<br>
>    Protocol = dumb-increment-protocol<br>
>    Upgrade = websocket<br>
>    Origin = <a href="https://192.168.1.6:7681" target="_blank">https://192.168.1.6:7681</a><br>
>    Key = flv4nyR7f+VEHFSWJXQxBA==<br>
>    Version = 13<br>
>    Extensions = x-webkit-deflate-frame<br>
>    Pragma: = no-cache<br>
>    Cache-Control: = no-cache<br>
>    Cookie: = test=LWS_1388753472_194286_COOKIE<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
<br>
</div></div>It's better not to use pthread_self but the api that gives the int thread id, since we store it in an int.<br>
<div><div class="h5"><br>
>    GET URI = /xxx<br>
>    Host = <a href="http://192.168.1.6:7681" target="_blank">192.168.1.6:7681</a><br>
>    Connection = Upgrade<br>
>    Protocol = lws-mirror-protocol<br>
>    Upgrade = websocket<br>
>     Origin = <a href="https://192.168.1.6:7681" target="_blank">https://192.168.1.6:7681</a><br>
>    Key = OXYhUJt7pkvdd72hJzPp5w==<br>
>    Version = 13<br>
>sampled_ppoll_tid: 0<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>    Extensions = x-webkit-deflate-frame<br>
>    Pragma: = no-cache<br>
>    Cache-Control: = no-cache<br>
>    Cookie: = test=LWS_1388753472_194286_COOKIE<br>
>sampled_ppoll_tid: -1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1678948608<br>
>kill(sampled_ppoll_tid, SIGUSR2)<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>sampled_ppoll_tid: 0<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1657694464<br>
>    GET URI = /favicon.ico<br>
>    Host = <a href="http://192.168.1.6:7681" target="_blank">192.168.1.6:7681</a><br>
>    Connection = keep-alive<br>
>    Accept: = */*<br>
>    Accept-Encoding: = gzip,deflate,sdch<br>
>    Accept-Language: = fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4<br>
>    Cookie: = test=LWS_1388753472_194286_COOKIE<br>
>sampled_ppoll_tid: -1657694464<br>
>LWS_CALLBACK_GET_THREAD_ID pthread_self():-1678948608<br>
>kill(sampled_ppoll_tid, SIGUSR2)<br>
><br>
>I continue my investigation.<br>
<br>
</div></div>I can't make much sense of the logging without timestamping.<br>
<br>
You can test the ppoll side by just making it wait in ppoll for a long time and use kill to fire a sigusr2 at it from another terminal and confirm the ppoll exits.<br>
<br>
Testing the whole thing needs the main ws protocol connection to be connected and idle until the other thread provokes it to do something.<br>
<span class="HOEnZb"><font color="#888888"><br>
-Andy<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
>Thanks for your the patch anyway.<br>
><br>
>BR,<br>
>Thomas<br>
><br>
><br>
>2014/1/3 "Andy Green (林安廸)" <<a href="mailto:andy@warmcat.com">andy@warmcat.com</a>><br>
><br>
>> On 01/01/14 22:38, the mail apparently from Andy Green included:<br>
>><br>
>><br>
>>><br>
>>> Thomas Spitz <<a href="mailto:thomas.spitz@hestia-france.com">thomas.spitz@hestia-france.com</a>> wrote:<br>
>>><br>
>>>> Hello Andy,<br>
>>>><br>
>>>> Have you had some time trying to replace poll by ppoll in order to<br>
>have<br>
>>>> poll triggered on signal from an external thread?<br>
>>>><br>
>>><br>
>>> Not yet... in Taiwan the big holiday is Chinese New Year in a few<br>
>weeks.<br>
>>>  I'm still interested in doing it, the weekend is the most likely<br>
>time.<br>
>>><br>
>><br>
>> Please have a look at this:<br>
>><br>
>> <a href="http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/commit/?id=" target="_blank">http://git.libwebsockets.org/cgi-bin/cgit/libwebsockets/commit/?id=</a><br>
>> 3b3fa9e2086da6157289141e0b6fe1e5035bad25<br>
>><br>
>> I didn't test it because I don't have a threaded user code, but it<br>
>should<br>
>> be pretty close if not workable already.<br>
>><br>
>> Note the comment in the commit log, you have to actively enable this<br>
>code<br>
>> (I wasn't able to find a way for the compiler to understand if it had<br>
>> ppoll() or not).<br>
>><br>
>> ppoll() is a GNU extension so if this is useful, we'll need to add it<br>
>as a<br>
>> CMake-time option.<br>
>><br>
>> -Andy<br>
>><br>
>><br>
>><br>
>>  -Andy<br>
>>><br>
>>>  At the present your lib works very well with intensive data submit<br>
>from<br>
>>>> external thread.<br>
>>>><br>
>>>> Happy new year to everyone.<br>
>>>><br>
>>>> BR,<br>
>>>><br>
>>>> Thomas<br>
>>>><br>
>>>><br>
>>>> On 25 Dec 2013 15:24, Andy Green (林安廸) <<a href="mailto:andy@warmcat.com">andy@warmcat.com</a>> wrote:<br>
>>>><br>
>>>>  On 25/12/13 20:14, the mail apparently from Thomas Spitz included:<br>
>>>>><br>
>>>>>       The choices seem to boil down to this kind of "add a fake<br>
>>>>>>      descriptor" thing (although everything, including the<br>
>"interrupt<br>
>>>>>><br>
>>>>> the<br>
>>>><br>
>>>>>      poll" descriptor and the use of it should be defined inside<br>
>the<br>
>>>>>>      library), or maybe change to use ppoll() and fire signals at<br>
>it.<br>
>>>>>><br>
>>>>>> ppoll() could be an interesting solution but it only interrupt<br>
>the<br>
>>>>>><br>
>>>>> poll.<br>
>>>><br>
>>>>><br>
>>>>>><br>
>>>>> I think that's all we need to do.<br>
>>>>><br>
>>>>> Latency is only coming this way on an idle system where we are<br>
>>>>><br>
>>>> sleeping in<br>
>>>><br>
>>>>> the poll(), but another thread asked to change what a pollfd was<br>
>>>>><br>
>>>> waiting on.<br>
>>>><br>
>>>>><br>
>>>>> As you pointed out originally, under those circumstances the<br>
>changed<br>
>>>>> pollfd rules won't be seen and handled -- if every fd is idle for<br>
>the<br>
>>>>> events it started out with -- until the poll() timeout expires.<br>
>>>>><br>
>>>>> Although in other use-cases this isn't that realistic as a<br>
>problem,<br>
>>>>><br>
>>>> since<br>
>>>><br>
>>>>> some deal with tens of thousands of simultaneous connections and<br>
>>>>><br>
>>>> usually<br>
>>>><br>
>>>>> someone is breaking the poll after a short time for service, in<br>
>other<br>
>>>>><br>
>>>> use<br>
>>>><br>
>>>>> cases it is realistic.  You can attack it by reducing the poll<br>
>sleep<br>
>>>>><br>
>>>> period<br>
>>>><br>
>>>>> but then you're looking at maybe hundreds of wakes a second on<br>
>what<br>
>>>>><br>
>>>> should<br>
>>>><br>
>>>>> be an idle system, needlessly bad for power.<br>
>>>>><br>
>>>>> If we provided a way for those use-cases to have very long poll()<br>
>>>>><br>
>>>> timeouts<br>
>>>><br>
>>>>> and minimal latency it's good I think, so long as it doesn't<br>
>burden<br>
>>>>><br>
>>>> or make<br>
>>>><br>
>>>>> problems when it's not wanted or needed.<br>
>>>>><br>
>>>>>   I was thinking of interrupting poll() using a named pipe in<br>
>which I<br>
>>>>><br>
>>>>>> would have told lws which wsi it needs to write to. The complete<br>
>>>>>><br>
>>>>> process<br>
>>>><br>
>>>>> would have been the following:<br>
>>>>>><br>
>>>>>><br>
>>>>> No it's not a good way... lws already has a good semantic in<br>
>poll()<br>
>>>>><br>
>>>> for<br>
>>>><br>
>>>>> understanding who needed service.  This would be a lot of new<br>
>stuff<br>
>>>>><br>
>>>> doing<br>
>>>><br>
>>>>> the same job that only works in the multithreaded case.<br>
>>>>><br>
>>>>>   1) Before libwebsocket_create_context(), I create the named<br>
>pipe.<br>
>>>>><br>
>>>>>> 2) For every client connection, I book for a shm<br>
>>>>>> in LWS_CALLBACK_ESTABLISHED through which I will share incoming<br>
>data<br>
>>>>>> with my main thread<br>
>>>>>> 3) My main thread process the incoming data and store the answer<br>
>>>>>><br>
>>>>> into<br>
>>>><br>
>>>>> the shm. It then indicates lws that an answer is ready for a given<br>
>>>>>><br>
>>>>> wsi<br>
>>>><br>
>>>>> indicating the ID of the shm in the named pipe<br>
>>>>>> 4) lws poll() is interupted and it knows immediatly which wsi it<br>
>>>>>><br>
>>>>> needs<br>
>>>><br>
>>>>> to write to thanks to the ID of the shm. If the wsi is closed in<br>
>the<br>
>>>>>> meanwhile, lws indicate it to the shm in LWS_CALLBACK_CLOSED<br>
>>>>>><br>
>>>>>> If I use ppoll(), I could keep almost the same principle but I<br>
>would<br>
>>>>>> then need to add a SIGUSR1 and a handler OR loop through my<br>
>client<br>
>>>>>><br>
>>>>> shm<br>
>>>><br>
>>>>> array each time ppoll() got interupted with EINTR flag set...<br>
>>>>>><br>
>>>>> Finally I<br>
>>>><br>
>>>>> am still wondering whether my solution is not simpler?<br>
>>>>>><br>
>>>>>><br>
>>>>> That solution is basically a threaded rewrite of lws not using<br>
>>>>><br>
>>>> poll(). If<br>
>>>><br>
>>>>> you're interested to do that I don't want to discourage you, but<br>
>it's<br>
>>>>> something different from lws then.  Of course lws is liberally<br>
>>>>><br>
>>>> licensed so<br>
>>>><br>
>>>>> you're welcome to build on it if you have a compatible license.<br>
>>>>><br>
>>>>> However, if you think about larger scale servers, which do exist<br>
>>>>><br>
>>>> using<br>
>>>><br>
>>>>> lws, "knowing the exact (single) wsi" that woke it is not useful<br>
>when<br>
>>>>><br>
>>>> there<br>
>>>><br>
>>>>> may be hundreds of fds needing service each poll().<br>
>>>>><br>
>>>>>       Either way lws_change_pollfd() is central to the solution.<br>
>>>>><br>
>>>>>><br>
>>>>>> With my solution or even ppoll one, I don't see when I need to<br>
>>>>>> calllws_change_pollfd() especially as lws_change_pollfd needs a<br>
>>>>>><br>
>>>>> pointer<br>
>>>><br>
>>>>> to wsi which I cannot give as my interrupt concerns the complete<br>
>>>>>><br>
>>>>> context<br>
>>>><br>
>>>>> and not a special wsi...?I must miss a point.<br>
>>>>>><br>
>>>>>><br>
>>>>> lws_change_pollfd() is the point that any code which wants to<br>
>change<br>
>>>>><br>
>>>> the<br>
>>>><br>
>>>>> events on a pollfd ends up at now.  And changing the event on a<br>
>>>>><br>
>>>> pollfd is<br>
>>>><br>
>>>>> the definition of the cause of latency (when poll() is idle and<br>
>with<br>
>>>>> relatively long timeout).<br>
>>>>><br>
>>>>> So whether it is doing rx flow control or wait on being able to<br>
>send,<br>
>>>>><br>
>>>> that<br>
>>>><br>
>>>>> function is the place to signal to break the poll() one way or the<br>
>>>>><br>
>>>> other.<br>
>>>><br>
>>>>><br>
>>>>>       If you pick a signal like SIGUSR1 and install a do-nothing<br>
>>>>><br>
>>>> handler<br>
>>>><br>
>>>>>      for it, firing SIGUSR1 at the process from itself in<br>
>>>>>>      lws_change_pollfd() and using ppoll() could be a really<br>
>small<br>
>>>>>><br>
>>>>> and<br>
>>>><br>
>>>>>      robust solution.<br>
>>>>>>      Since the signal is handled it doesn't do anything except<br>
>>>>>><br>
>>>>> interrupt<br>
>>>><br>
>>>>>      the ppoll causing a pollfd reload.<br>
>>>>>>      You only need to fire the signal the first time anything<br>
>wants<br>
>>>>>><br>
>>>>> to<br>
>>>><br>
>>>>>      interrupt the wait *from another thread* (because if the lws<br>
>>>>>><br>
>>>>> thread<br>
>>>><br>
>>>>>      is in poll(), it isn't doing anything else).  If a pollfd<br>
>raced<br>
>>>>>><br>
>>>>> it<br>
>>>><br>
>>>>>      and changed first, there's no problem with an additional<br>
>signal<br>
>>>>>>      interrupting the next ppoll loop.<br>
>>>>>><br>
>>>>>> Ideally, if it is not too much to ask, a simple example of code<br>
>>>>>><br>
>>>>> would be<br>
>>>><br>
>>>>> ideal.<br>
>>>>>><br>
>>>>>><br>
>>>>> I may have some time tomorrow to give this a try.<br>
>>>>><br>
>>>>> -Andy<br>
>>>>><br>
>>>><br>
>><br>
<br>
</div></div></blockquote></div><br></div>