Skip to content

Commit cf29e22

Browse files
committed
Stop the test if one of the threads terminated
1 parent e004dc3 commit cf29e22

File tree

5 files changed

+79
-14
lines changed

5 files changed

+79
-14
lines changed

src/iperf.h

+1
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ struct iperf_stream
204204
int remote_port;
205205
int socket;
206206
int id;
207+
int thread_number;
207208
int sender;
208209
/* XXX: is settings just a pointer to the same struct in iperf_test? if not,
209210
should it be? */

src/iperf_api.h

+1
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ enum {
476476
IEPTHREADJOIN=152, // Unable to join thread (check perror)
477477
IEPTHREADATTRINIT=153, // Unable to initialize thread attribute (check perror)
478478
IEPTHREADATTRDESTROY=154, // Unable to destroy thread attribute (check perror)
479+
IEPTHREADNOTRUNNING=155, // A thread stopped running unexpectedly
479480
/* Stream errors */
480481
IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror)
481482
IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror)

src/iperf_client_api.c

+39-10
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@
5151
#endif /* TCP_CA_NAME_MAX */
5252
#endif /* HAVE_TCP_CONGESTION */
5353

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+
5458
void *
5559
iperf_client_worker_run(void *s) {
5660
struct iperf_stream *sp = (struct iperf_stream *) s;
@@ -75,6 +79,12 @@ iperf_client_worker_run(void *s) {
7579
return NULL;
7680

7781
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);
7888
return NULL;
7989
}
8090

@@ -545,6 +555,7 @@ iperf_run_client(struct iperf_test * test)
545555
int64_t timeout_us;
546556
int64_t rcv_timeout_us;
547557
int i_errno_save;
558+
int total_num_streams = 0;
548559

549560
if (NULL == test)
550561
{
@@ -678,13 +689,23 @@ iperf_run_client(struct iperf_test * test)
678689
goto cleanup_and_fail;
679690
}
680691

692+
pthread_mutex_lock(&running_mutex);
693+
running_threads = 0;
694+
total_num_streams = 0;
695+
pthread_mutex_unlock(&running_mutex);
681696
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+
682703
if (pthread_create(&(sp->thr), &attr, &iperf_client_worker_run, sp) != 0) {
683704
i_errno = IEPTHREADCREATE;
684705
goto cleanup_and_fail;
685706
}
686707
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);
688709
}
689710
}
690711
if (test->debug_level >= DEBUG_LEVEL_INFO) {
@@ -725,18 +746,18 @@ iperf_run_client(struct iperf_test * test)
725746
if (rc != 0 && rc != ESRCH) {
726747
i_errno = IEPTHREADCANCEL;
727748
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));
729750
goto cleanup_and_fail;
730751
}
731752
rc = pthread_join(sp->thr, NULL);
732753
if (rc != 0 && rc != ESRCH) {
733754
i_errno = IEPTHREADJOIN;
734755
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));
736757
goto cleanup_and_fail;
737758
}
738759
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);
740761
}
741762
}
742763
}
@@ -751,6 +772,14 @@ iperf_run_client(struct iperf_test * test)
751772
if (iperf_set_send_state(test, TEST_END) != 0)
752773
goto cleanup_and_fail;
753774
}
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+
754783
}
755784
}
756785

@@ -763,18 +792,18 @@ iperf_run_client(struct iperf_test * test)
763792
if (rc != 0 && rc != ESRCH) {
764793
i_errno = IEPTHREADCANCEL;
765794
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));
767796
goto cleanup_and_fail;
768797
}
769798
rc = pthread_join(sp->thr, NULL);
770799
if (rc != 0 && rc != ESRCH) {
771800
i_errno = IEPTHREADJOIN;
772801
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));
774803
goto cleanup_and_fail;
775804
}
776805
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);
778807
}
779808
}
780809
}
@@ -804,16 +833,16 @@ iperf_run_client(struct iperf_test * test)
804833
if (rc != 0 && rc != ESRCH) {
805834
i_errno = IEPTHREADCANCEL;
806835
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));
808837
}
809838
rc = pthread_join(sp->thr, NULL);
810839
if (rc != 0 && rc != ESRCH) {
811840
i_errno = IEPTHREADJOIN;
812841
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));
814843
}
815844
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);
817846
}
818847
}
819848
if (test->debug_level >= DEBUG_LEVEL_INFO) {

src/iperf_error.c

+4
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,10 @@ iperf_strerror(int int_errno)
507507
snprintf(errstr, len, "unable to destroy thread attributes");
508508
perr = 1;
509509
break;
510+
case IEPTHREADNOTRUNNING:
511+
snprintf(errstr, len, "a thread stopped running unexpectedly");
512+
perr = 1;
513+
break;
510514
default:
511515
snprintf(errstr, len, "int_errno=%d", int_errno);
512516
perr = 1;

src/iperf_server_api.c

+34-4
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@
6666
#endif /* TCP_CA_NAME_MAX */
6767
#endif /* HAVE_TCP_CONGESTION */
6868

69+
// variable for number of active threads count
70+
static volatile int running_threads = 0;
71+
static pthread_mutex_t running_mutex = PTHREAD_MUTEX_INITIALIZER;
72+
6973
void *
7074
iperf_server_worker_run(void *s) {
7175
struct iperf_stream *sp = (struct iperf_stream *) s;
@@ -90,6 +94,12 @@ iperf_server_worker_run(void *s) {
9094
return NULL;
9195

9296
cleanup_and_fail:
97+
if (test->debug_level >= DEBUG_LEVEL_INFO) {
98+
iperf_printf(sp->test, "Thread number %d FD %d terminated unexpectedly\n", sp->thread_number, sp->socket);
99+
}
100+
pthread_mutex_lock(&running_mutex);
101+
running_threads--; // Indicate that the thread failed
102+
pthread_mutex_unlock(&running_mutex);
93103
return NULL;
94104
}
95105

@@ -424,16 +434,16 @@ cleanup_server(struct iperf_test *test)
424434
if (rc != 0 && rc != ESRCH) {
425435
i_errno = IEPTHREADCANCEL;
426436
errno = rc;
427-
iperf_err(test, "cleanup_server in pthread_cancel - %s", iperf_strerror(i_errno));
437+
iperf_err(test, "cleanup_server in pthread_cancel of thread %d - %s", sp->thread_number, iperf_strerror(i_errno));
428438
}
429439
rc = pthread_join(sp->thr, NULL);
430440
if (rc != 0 && rc != ESRCH) {
431441
i_errno = IEPTHREADJOIN;
432442
errno = rc;
433-
iperf_err(test, "cleanup_server in pthread_join - %s", iperf_strerror(i_errno));
443+
iperf_err(test, "cleanup_server in pthread_join of thread %d - %s", sp->thread_number, iperf_strerror(i_errno));
434444
}
435445
if (test->debug_level >= DEBUG_LEVEL_INFO) {
436-
iperf_printf(test, "Thread FD %d stopped\n", sp->socket);
446+
iperf_printf(test, "Thread number %d FD %d stopped\n", sp->thread_number, sp->socket);
437447
}
438448
}
439449
i_errno = i_errno_save;
@@ -511,6 +521,7 @@ iperf_run_server(struct iperf_test *test)
511521
int64_t t_usecs;
512522
int64_t timeout_us;
513523
int64_t rcv_timeout_us;
524+
int total_num_streams = 0;
514525

515526
if (test->logfile)
516527
if (iperf_open_logfile(test) < 0)
@@ -872,14 +883,24 @@ iperf_run_server(struct iperf_test *test)
872883
cleanup_server(test);
873884
};
874885

886+
pthread_mutex_lock(&running_mutex);
887+
running_threads = 0;
888+
total_num_streams = 0;
889+
pthread_mutex_unlock(&running_mutex);
875890
SLIST_FOREACH(sp, &test->streams, streams) {
891+
pthread_mutex_lock(&running_mutex);
892+
running_threads++; // Count running threads
893+
sp->thread_number = running_threads;
894+
pthread_mutex_unlock(&running_mutex);
895+
total_num_streams++;
896+
876897
if (pthread_create(&(sp->thr), &attr, &iperf_server_worker_run, sp) != 0) {
877898
i_errno = IEPTHREADCREATE;
878899
cleanup_server(test);
879900
return -1;
880901
}
881902
if (test->debug_level >= DEBUG_LEVEL_INFO) {
882-
iperf_printf(test, "Thread FD %d created\n", sp->socket);
903+
iperf_printf(test, "Thread number %d FD %d created\n", sp->thread_number, sp->socket);
883904
}
884905
}
885906
if (test->debug_level >= DEBUG_LEVEL_INFO) {
@@ -893,6 +914,15 @@ iperf_run_server(struct iperf_test *test)
893914
}
894915
}
895916

917+
/* Terminate if any thread failed */
918+
if (test->state == TEST_RUNNING) {
919+
if (running_threads != total_num_streams) {
920+
i_errno = IEPTHREADNOTRUNNING;
921+
iperf_err(test, "Number of running threads is %d but expected %d", running_threads, test->num_streams);
922+
cleanup_server(test);
923+
}
924+
}
925+
896926
if (result == 0 ||
897927
(timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0)) {
898928
/* Run the timers. */

0 commit comments

Comments
 (0)