<div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-size:small">Hi Richard,</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Sep 24, 2019 at 8:42 PM Richard Palethorpe <<a href="mailto:rpalethorpe@suse.de">rpalethorpe@suse.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail_default" style="font-size:small">...</span><br>
It can just be<br>
<br>
if (!pair->exit) {<br>
   ...<br>
}<br>
<br>
We want to join the thread and set the func pointer to zero regardless<br>
of how we exit.<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">OK.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> +                     SAFE_PTHREAD_JOIN(pair->thread_b, NULL);<br>
> +                     pair->thread_b = 0;<br>
> +             } else {<br>
<br>
I suggest still setting pair->exit here and maybe sleeping for<br>
100ms. This gives thread B chance to exit gracefully. It is possible<br>
that if thread B is in a spin loop then the thread won't be cancelled as<br>
asynchronous cancellation is not guaranteed by POSIX.<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">Good suggestion. That'd be better to give one more time for thread B exiting gracefully.</div></div><div class="gmail_default" style="font-size:small"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> +                     pthread_cancel(pair->thread_b);<br>
> +                     pair->thread_b = 0;<br>
> +             }<br>
>       }<br>
>  }<br>
><br>
> @@ -271,8 +276,11 @@ static void tst_fzsync_pair_reset(struct tst_fzsync_pair *pair,<br>
>       pair->a_cntr = 0;<br>
>       pair->b_cntr = 0;<br>
>       pair->exit = 0;<br>
> -     if (run_b)<br>
> +     if (run_b) {<br>
> +             pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);<br>
> +             pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);<br>
<br>
These need to go inside thread B unless I am mistaken. Which means you<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">Right.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
must wrap the user supplied function. You can create a function which<br>
accepts a pointer to some contiguous memory containing the user supplied function<br>
pointer and the user supplied arg pointer.<br></blockquote><div><br></div><div><div class="gmail_default" style="font-size:small">Since you have fixed the function format of thread B as void *(*run_b)(void *) in tst_fzsync_pair_reset(), which means we have no need to take care of the function arg pointer anymore.</div><br></div><div class="gmail_default" style="font-size:small">So just like what I did in V2, the wrapper function could steal the real run_b address from pthread_create(..., wrap_run_b, run_b) parameter.</div></div><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div>Regards,<br></div><div>Li Wang<br></div></div></div></div>