[LTP] [PATCH RFC] fzsync: tst_fzsync_pair_wait exit when parent hit accidental break

Li Wang liwang@redhat.com
Mon Jan 7 07:51:22 CET 2019


Richard Palethorpe <rpalethorpe@suse.de> wrote:
>
> This is how it worked before, so it is fairly safe. However I don't like
> atomically checking for the exit value on every spin of the delay
> loop. Also because setting exit just causes it to drop through there is
> still the (theoretical) risk of it getting stuck on another operation
> before breaking out of thread B's main loop.

Yes, and I noticed you removed the exit checking in last update, but I
didn't realize that thread B will fall into infinite loop when parent
is break abnormally.

>
> Also removing the exit variable makes formal verification a bit easier.

Good point.

>
> Another option might be to use pthread_kill with a realtime signal and
> a signal handler which immediately exits the current thread. I am not
> sure how much complexity that will introduce though?

Well we can have a try, seems the only disadvantage of this method is
thread_B sets signal handler at each loop start in tst_fzsync_run_b
repeatedly.

Not sure if I understand correctly, what drafted in my mind is:

diff --git a/include/tst_fuzzy_sync.h b/include/tst_fuzzy_sync.h
index de0402c9b..6ef6bee01 100644
--- a/include/tst_fuzzy_sync.h
+++ b/include/tst_fuzzy_sync.h
@@ -63,6 +63,8 @@
 #include <time.h>
 #include <math.h>
 #include <stdlib.h>
+#include <pthread.h>
+#include <errno.h>
 #include "tst_atomic.h"
 #include "tst_timer.h"
 #include "tst_safe_pthread.h"
@@ -156,8 +158,6 @@ struct tst_fzsync_pair {
        int a_cntr;
        /** Internal; Atomic counter used by fzsync_pair_wait() */
        int b_cntr;
-       /** Internal; Used by tst_fzsync_pair_exit() and fzsync_pair_wait() */
-       int exit;
        /**
         * The maximum desired execution time as a proportion of the timeout
         *
@@ -217,13 +217,28 @@ static void tst_fzsync_pair_init(struct
tst_fzsync_pair *pair)
  */
 static void tst_fzsync_pair_cleanup(struct tst_fzsync_pair *pair)
 {
+       int kill_ret;
+
        if (pair->thread_b) {
-               tst_atomic_store(1, &pair->exit);
-               SAFE_PTHREAD_JOIN(pair->thread_b, NULL);
-               pair->thread_b = 0;
+               kill_ret = pthread_kill(pair->thread_b, SIGUSR1);
+
+               if(kill_ret == 0) {
+                       SAFE_PTHREAD_JOIN(pair->thread_b, NULL);
+                       pair->thread_b = 0;
+               } else if (kill_ret == EINVAL) {
+                       tst_res(TINFO, "Invalid signal was specified");
+               } else if (kill_ret == ESRCH) {
+                       tst_res(TINFO, "thread_b is not exist");
+               }
        }
 }

+static void sighandler(int sig)
+{
+       if (sig == SIGUSR1)
+               pthread_exit(NULL);
+}
+
 /**
  * Zero some stat fields
  *
@@ -270,7 +285,6 @@ static void tst_fzsync_pair_reset(struct
tst_fzsync_pair *pair,

        pair->a_cntr = 0;
        pair->b_cntr = 0;
-       pair->exit = 0;
        if (run_b)
                SAFE_PTHREAD_CREATE(&pair->thread_b, 0, run_b, 0);

@@ -613,7 +627,6 @@ static inline int tst_fzsync_run_a(struct
tst_fzsync_pair *pair)
                exit = 1;
        }

-       tst_atomic_store(exit, &pair->exit);
        tst_fzsync_wait_a(pair);

        if (exit) {
@@ -632,8 +645,9 @@ static inline int tst_fzsync_run_a(struct
tst_fzsync_pair *pair)
  */
 static inline int tst_fzsync_run_b(struct tst_fzsync_pair *pair)
 {
+       SAFE_SIGNAL(SIGUSR1, sighandler);
        tst_fzsync_wait_b(pair);
-       return !tst_atomic_load(&pair->exit);
+       return 1;
 }

 /**


-- 
Regards,
Li Wang


More information about the ltp mailing list