51
51
#endif /* TCP_CA_NAME_MAX */
52
52
#endif /* HAVE_TCP_CONGESTION */
53
53
54
+ // variable for number of active threads count (for checking if any failed)
55
+ static volatile int running_threads = 0 ;
56
+ static pthread_mutex_t running_mutex = PTHREAD_MUTEX_INITIALIZER ;
57
+
54
58
void *
55
59
iperf_client_worker_run (void * s ) {
56
60
struct iperf_stream * sp = (struct iperf_stream * ) s ;
@@ -75,6 +79,12 @@ iperf_client_worker_run(void *s) {
75
79
return NULL ;
76
80
77
81
cleanup_and_fail :
82
+ if (test -> debug_level >= DEBUG_LEVEL_INFO ) {
83
+ iperf_printf (sp -> test , "Thread number %d FD %d terminated unexpectedly\n" , sp -> thread_number , sp -> socket );
84
+ }
85
+ pthread_mutex_lock (& running_mutex );
86
+ running_threads -- ; // Indicate that the thread failed
87
+ pthread_mutex_unlock (& running_mutex );
78
88
return NULL ;
79
89
}
80
90
@@ -545,6 +555,7 @@ iperf_run_client(struct iperf_test * test)
545
555
int64_t timeout_us ;
546
556
int64_t rcv_timeout_us ;
547
557
int i_errno_save ;
558
+ int total_num_streams = 0 ;
548
559
549
560
if (NULL == test )
550
561
{
@@ -678,13 +689,23 @@ iperf_run_client(struct iperf_test * test)
678
689
goto cleanup_and_fail ;
679
690
}
680
691
692
+ pthread_mutex_lock (& running_mutex );
693
+ running_threads = 0 ;
694
+ total_num_streams = 0 ;
695
+ pthread_mutex_unlock (& running_mutex );
681
696
SLIST_FOREACH (sp , & test -> streams , streams ) {
697
+ pthread_mutex_lock (& running_mutex );
698
+ running_threads ++ ; // Count running threads
699
+ sp -> thread_number = running_threads ;
700
+ pthread_mutex_unlock (& running_mutex );
701
+ total_num_streams ++ ;
702
+
682
703
if (pthread_create (& (sp -> thr ), & attr , & iperf_client_worker_run , sp ) != 0 ) {
683
704
i_errno = IEPTHREADCREATE ;
684
705
goto cleanup_and_fail ;
685
706
}
686
707
if (test -> debug_level >= DEBUG_LEVEL_INFO ) {
687
- iperf_printf (test , "Thread FD %d created\n" , sp -> socket );
708
+ iperf_printf (test , "Thread number %d using FD %d created\n" , sp -> thread_number , sp -> socket );
688
709
}
689
710
}
690
711
if (test -> debug_level >= DEBUG_LEVEL_INFO ) {
@@ -725,18 +746,18 @@ iperf_run_client(struct iperf_test * test)
725
746
if (rc != 0 && rc != ESRCH ) {
726
747
i_errno = IEPTHREADCANCEL ;
727
748
errno = rc ;
728
- iperf_err (test , "sender cancel in pthread_cancel - %s" , iperf_strerror (i_errno ));
749
+ iperf_err (test , "sender cancel in pthread_cancel of thread %d - %s" , sp -> thread_number , iperf_strerror (i_errno ));
729
750
goto cleanup_and_fail ;
730
751
}
731
752
rc = pthread_join (sp -> thr , NULL );
732
753
if (rc != 0 && rc != ESRCH ) {
733
754
i_errno = IEPTHREADJOIN ;
734
755
errno = rc ;
735
- iperf_err (test , "sender cancel in pthread_join - %s" , iperf_strerror (i_errno ));
756
+ iperf_err (test , "sender cancel in pthread_join of thread %d - %s" , sp -> thread_number , iperf_strerror (i_errno ));
736
757
goto cleanup_and_fail ;
737
758
}
738
759
if (test -> debug_level >= DEBUG_LEVEL_INFO ) {
739
- iperf_printf (test , "Thread FD %d stopped\n" , sp -> socket );
760
+ iperf_printf (test , "Thread number %d FD %d stopped\n" , sp -> thread_number , sp -> socket );
740
761
}
741
762
}
742
763
}
@@ -751,6 +772,14 @@ iperf_run_client(struct iperf_test * test)
751
772
if (iperf_set_send_state (test , TEST_END ) != 0 )
752
773
goto cleanup_and_fail ;
753
774
}
775
+
776
+ /* Terminate if one of the threads failed */
777
+ if (running_threads != total_num_streams ) {
778
+ i_errno = IEPTHREADNOTRUNNING ;
779
+ iperf_err (test , "Number of running threads is %d but expected %d" , running_threads , test -> num_streams );
780
+ goto cleanup_and_fail ;
781
+ }
782
+
754
783
}
755
784
}
756
785
@@ -763,18 +792,18 @@ iperf_run_client(struct iperf_test * test)
763
792
if (rc != 0 && rc != ESRCH ) {
764
793
i_errno = IEPTHREADCANCEL ;
765
794
errno = rc ;
766
- iperf_err (test , "receiver cancel in pthread_cancel - %s" , iperf_strerror (i_errno ));
795
+ iperf_err (test , "receiver cancel in pthread_cancel of thread %d - %s" , sp -> thread_number , iperf_strerror (i_errno ));
767
796
goto cleanup_and_fail ;
768
797
}
769
798
rc = pthread_join (sp -> thr , NULL );
770
799
if (rc != 0 && rc != ESRCH ) {
771
800
i_errno = IEPTHREADJOIN ;
772
801
errno = rc ;
773
- iperf_err (test , "receiver cancel in pthread_join - %s" , iperf_strerror (i_errno ));
802
+ iperf_err (test , "receiver cancel in pthread_join of thread %d - %s" , sp -> thread_number , iperf_strerror (i_errno ));
774
803
goto cleanup_and_fail ;
775
804
}
776
805
if (test -> debug_level >= DEBUG_LEVEL_INFO ) {
777
- iperf_printf (test , "Thread FD %d stopped\n" , sp -> socket );
806
+ iperf_printf (test , "Thread number %d FD %d stopped\n" , sp -> thread_number , sp -> socket );
778
807
}
779
808
}
780
809
}
@@ -804,16 +833,16 @@ iperf_run_client(struct iperf_test * test)
804
833
if (rc != 0 && rc != ESRCH ) {
805
834
i_errno = IEPTHREADCANCEL ;
806
835
errno = rc ;
807
- iperf_err (test , "cleanup_and_fail in pthread_cancel - %s" , iperf_strerror (i_errno ));
836
+ iperf_err (test , "cleanup_and_fail in pthread_cancel of thread %d - %s" , sp -> thread_number , iperf_strerror (i_errno ));
808
837
}
809
838
rc = pthread_join (sp -> thr , NULL );
810
839
if (rc != 0 && rc != ESRCH ) {
811
840
i_errno = IEPTHREADJOIN ;
812
841
errno = rc ;
813
- iperf_err (test , "cleanup_and_fail in pthread_join - %s" , iperf_strerror (i_errno ));
842
+ iperf_err (test , "cleanup_and_fail in pthread_join of thread %d - %s" , sp -> thread_number , iperf_strerror (i_errno ));
814
843
}
815
844
if (test -> debug_level >= DEBUG_LEVEL_INFO ) {
816
- iperf_printf (test , "Thread FD %d stopped\n" , sp -> socket );
845
+ iperf_printf (test , "Thread number %d FD %d stopped\n" , sp -> thread_number , sp -> socket );
817
846
}
818
847
}
819
848
if (test -> debug_level >= DEBUG_LEVEL_INFO ) {
0 commit comments