Improve thread reap handling
authorJens Axboe <jens.axboe@oracle.com>
Thu, 22 Feb 2007 10:53:00 +0000 (11:53 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Thu, 22 Feb 2007 10:53:00 +0000 (11:53 +0100)
It's a bit of a mess currently, streamline and clean it up.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
fio.c
fio.h
time.c

diff --git a/fio.c b/fio.c
index fad4cca76bbe2cb9781ad10183e0ab369d126ff2..0f72fd92c15c883e75603a19b2a4fc89e915ba6f 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -824,6 +824,8 @@ static void reap_threads(int *nr_running, int *t_rate, int *m_rate)
         */
        pending = cputhreads = 0;
        for_each_td(td, i) {
         */
        pending = cputhreads = 0;
        for_each_td(td, i) {
+               int flags;
+
                /*
                 * ->io_ops is NULL for a thread that has closed its
                 * io engine
                /*
                 * ->io_ops is NULL for a thread that has closed its
                 * io engine
@@ -831,65 +833,57 @@ static void reap_threads(int *nr_running, int *t_rate, int *m_rate)
                if (td->io_ops && td->io_ops->flags & FIO_CPUIO)
                        cputhreads++;
 
                if (td->io_ops && td->io_ops->flags & FIO_CPUIO)
                        cputhreads++;
 
-               if (td->runstate < TD_EXITED) {
-                       /*
-                        * check if someone quit or got killed in an unusual way
-                        */
-                       ret = waitpid(td->pid, &status, WNOHANG);
-                       if (ret < 0) {
-                               if (errno == ECHILD) {
-                                       log_err("fio: pid=%d disappeared\n", td->pid);
-                                       td_set_runstate(td, TD_REAPED);
-                                       goto reaped;
-                               }
-                               perror("waitpid");
-                       } else if ((ret == td->pid) && WIFSIGNALED(status)) {
+               if (!td->pid || td->runstate == TD_REAPED)
+                       continue;
+
+               flags = WNOHANG;
+               if (td->runstate == TD_EXITED)
+                       flags = 0;
+
+               /*
+                * check if someone quit or got killed in an unusual way
+                */
+               ret = waitpid(td->pid, &status, flags);
+               if (ret < 0) {
+                       if (errno == ECHILD) {
+                               log_err("fio: pid=%d disappeared %d\n", td->pid, td->runstate);
+                               td_set_runstate(td, TD_REAPED);
+                               goto reaped;
+                       }
+                       perror("waitpid");
+               } else if (ret == td->pid) {
+                       if (WIFSIGNALED(status)) {
                                int sig = WTERMSIG(status);
 
                                log_err("fio: pid=%d, got signal=%d\n", td->pid, sig);
                                td_set_runstate(td, TD_REAPED);
                                goto reaped;
                        }
                                int sig = WTERMSIG(status);
 
                                log_err("fio: pid=%d, got signal=%d\n", td->pid, sig);
                                td_set_runstate(td, TD_REAPED);
                                goto reaped;
                        }
-               }
-
-               if (td->runstate != TD_EXITED) {
-                       if (td->runstate < TD_RUNNING)
-                               pending++;
-
-                       continue;
-               }
-
-               if (td->error)
-                       exit_value++;
-
-               td_set_runstate(td, TD_REAPED);
-
-               if (td->use_thread) {
-                       long ret;
-
-                       if (pthread_join(td->thread, (void *) &ret))
-                               perror("thread_join");
-               } else {
-                       int status;
-
-                       ret = waitpid(td->pid, &status, 0);
-                       if (ret < 0) {
-                               if (errno == ECHILD) {
-                                       log_err("fio: pid=%d disappeared\n", td->pid);
-                                       td_set_runstate(td, TD_REAPED);
-                                       goto reaped;
+                       if (WIFEXITED(status)) {
+                               if (WEXITSTATUS(status) && !td->error)
+                                       td->error = WEXITSTATUS(status);
+                               if (td->use_thread) {
+                                       long ret;
+
+                                       if (pthread_join(td->thread, (void *) &ret))
+                                               perror("pthread_join");
                                }
                                }
-                               perror("waitpid");
-                       } else if (WIFEXITED(status) && WEXITSTATUS(status)) {
-                               if (!exit_value)
-                                       exit_value++;
+                               td_set_runstate(td, TD_REAPED);
+                               goto reaped;
                        }
                }
 
                        }
                }
 
+               /*
+                * thread is not dead, continue
+                */
+               continue;
 reaped:
                (*nr_running)--;
                (*m_rate) -= td->ratemin;
                (*t_rate) -= td->rate;
 reaped:
                (*nr_running)--;
                (*m_rate) -= td->ratemin;
                (*t_rate) -= td->rate;
+
+               if (td->error)
+                       exit_value++;
        }
 
        if (*nr_running == cputhreads && !pending)
        }
 
        if (*nr_running == cputhreads && !pending)
@@ -945,6 +939,8 @@ static void run_threads(void)
                init_disk_util(td);
        }
 
                init_disk_util(td);
        }
 
+       set_genesis_time();
+
        while (todo) {
                struct thread_data *map[MAX_JOBS];
                struct timeval this_start;
        while (todo) {
                struct thread_data *map[MAX_JOBS];
                struct timeval this_start;
@@ -1103,6 +1099,8 @@ int main(int argc, char *argv[])
                setup_log(&agg_io_log[DDIR_WRITE]);
        }
 
                setup_log(&agg_io_log[DDIR_WRITE]);
        }
 
+       set_genesis_time();
+
        disk_util_timer_arm();
 
        run_threads();
        disk_util_timer_arm();
 
        run_threads();
diff --git a/fio.h b/fio.h
index c1c71465b8789ada64ebf51a8c611358ca1e6fac..7a4b1d19c8ebfa527814bee59976b014b5de9a99 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -577,6 +577,7 @@ extern void usec_sleep(struct thread_data *, unsigned long);
 extern void rate_throttle(struct thread_data *, unsigned long, unsigned int, int);
 extern void fill_start_time(struct timeval *);
 extern void fio_gettime(struct timeval *, void *);
 extern void rate_throttle(struct thread_data *, unsigned long, unsigned int, int);
 extern void fill_start_time(struct timeval *);
 extern void fio_gettime(struct timeval *, void *);
+extern void set_genesis_time(void);
 
 /*
  * Init functions
 
 /*
  * Init functions
diff --git a/time.c b/time.c
index 08ef078277ba125d43d1ce956db2ea92091e0793..11ee0e07b94a5030cf79817fda5ce8609320bf81 100644 (file)
--- a/time.c
+++ b/time.c
@@ -142,8 +142,6 @@ static void fio_init time_init(void)
 {
        int i;
 
 {
        int i;
 
-       fio_gettime(&genesis, NULL);
-
        /*
         * Check the granularity of the nanosleep function
         */
        /*
         * Check the granularity of the nanosleep function
         */
@@ -164,6 +162,11 @@ static void fio_init time_init(void)
        }
 }
 
        }
 }
 
+void set_genesis_time(void)
+{
+       fio_gettime(&genesis, NULL);
+}
+
 void fill_start_time(struct timeval *t)
 {
        memcpy(t, &genesis, sizeof(genesis));
 void fill_start_time(struct timeval *t)
 {
        memcpy(t, &genesis, sizeof(genesis));