From 081ba8e4e9ddeaa7991728ce12f0a9ee88f00a32 Mon Sep 17 00:00:00 2001 From: "Bruce A. Mah" Date: Wed, 16 Apr 2014 16:23:13 -0700 Subject: [PATCH] Commit a version of the patch for #125 for testing. Originally submitted by: @i2aaron --- examples/mic.c | 3 -- src/iperf.h | 1 - src/iperf_api.c | 13 ------ src/iperf_api.h | 2 - src/iperf_client_api.c | 96 ++++++++++++------------------------------ src/iperf_server_api.c | 2 + src/main.c | 3 -- src/net.c | 8 ++-- 8 files changed, 33 insertions(+), 95 deletions(-) diff --git a/examples/mic.c b/examples/mic.c index 6fd6484..7d1d9d5 100644 --- a/examples/mic.c +++ b/examples/mic.c @@ -36,9 +36,6 @@ main( int argc, char** argv ) iperf_defaults( test ); iperf_set_verbose( test, 1 ); - /* This main program doesn't use SIGALRM, so the iperf API may use it. */ - iperf_set_test_may_use_sigalrm(test, 1); - iperf_set_test_role( test, 'c' ); iperf_set_test_server_hostname( test, host ); iperf_set_test_server_port( test, port ); diff --git a/src/iperf.h b/src/iperf.h index 0b4bb4d..0c5c4de 100644 --- a/src/iperf.h +++ b/src/iperf.h @@ -193,7 +193,6 @@ struct iperf_test int debug; /* -d option - enable debug */ int multisend; - int may_use_sigalrm; char *json_output_string; /* rendered JSON output if json_output is set */ /* Select related parameters */ diff --git a/src/iperf_api.c b/src/iperf_api.c index e6bc671..6c00b31 100644 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -215,12 +215,6 @@ iperf_get_test_zerocopy(struct iperf_test *ipt) return ipt->zerocopy; } -int -iperf_get_test_may_use_sigalrm(struct iperf_test *ipt) -{ - return ipt->may_use_sigalrm; -} - char iperf_get_test_unit_format(struct iperf_test *ipt) { @@ -362,12 +356,6 @@ iperf_set_test_zerocopy(struct iperf_test *ipt, int zerocopy) ipt->zerocopy = zerocopy; } -void -iperf_set_test_may_use_sigalrm(struct iperf_test *ipt, int may_use_sigalrm) -{ - ipt->may_use_sigalrm = may_use_sigalrm; -} - void iperf_set_test_unit_format(struct iperf_test *ipt, char unit_format) { @@ -1604,7 +1592,6 @@ iperf_defaults(struct iperf_test *testp) memset(testp->cookie, 0, COOKIE_SIZE); testp->multisend = 10; /* arbitrary */ - testp->may_use_sigalrm = 0; /* Set up protocol list */ SLIST_INIT(&testp->streams); diff --git a/src/iperf_api.h b/src/iperf_api.h index ea5eb2c..644ca49 100644 --- a/src/iperf_api.h +++ b/src/iperf_api.h @@ -70,7 +70,6 @@ int iperf_get_test_protocol_id( struct iperf_test* ipt ); int iperf_get_test_json_output( struct iperf_test* ipt ); char* iperf_get_test_json_output_string ( struct iperf_test* ipt ); int iperf_get_test_zerocopy( struct iperf_test* ipt ); -int iperf_get_test_may_use_sigalrm( struct iperf_test* ipt ); /* Setter routines for some fields inside iperf_test. */ void iperf_set_verbose( struct iperf_test* ipt, int verbose ); @@ -92,7 +91,6 @@ void iperf_set_test_reverse( struct iperf_test* ipt, int reverse ); void iperf_set_test_json_output( struct iperf_test* ipt, int json_output ); int iperf_has_zerocopy( void ); void iperf_set_test_zerocopy( struct iperf_test* ipt, int zerocopy ); -void iperf_set_test_may_use_sigalrm( struct iperf_test* ipt, int may_use_sigalrm ); /** * exchange_parameters - handles the param_Exchange part for client diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c index e19aea2..0976b07 100644 --- a/src/iperf_client_api.c +++ b/src/iperf_client_api.c @@ -315,26 +315,15 @@ sigend_handler(int sig) } -typedef enum { cm_select, cm_itimer } cm_t; - -static int sigalrm_triggered; - -static void -sigalrm_handler(int sig) -{ - sigalrm_triggered = 1; -} - int iperf_run_client(struct iperf_test * test) { - cm_t concurrency_model; int startup; int result = 0; fd_set read_set, write_set; struct timeval now; struct timeval* timeout = NULL; - struct itimerval itv; + struct iperf_stream *sp; /* Termination signals. */ iperf_catch_sigend(sigend_handler); @@ -367,26 +356,22 @@ iperf_run_client(struct iperf_test * test) cpu_util(NULL); startup = 1; - concurrency_model = cm_select; /* always start in select mode */ while (test->state != IPERF_DONE) { - - if (concurrency_model == cm_select) { - memcpy(&read_set, &test->read_set, sizeof(fd_set)); - memcpy(&write_set, &test->write_set, sizeof(fd_set)); - (void) gettimeofday(&now, NULL); - timeout = tmr_timeout(&now); - result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout); - if (result < 0 && errno != EINTR) { - i_errno = IESELECT; - return -1; - } - if (result > 0) { - if (FD_ISSET(test->ctrl_sck, &read_set)) { - if (iperf_handle_message_client(test) < 0) { - return -1; - } - FD_CLR(test->ctrl_sck, &read_set); + memcpy(&read_set, &test->read_set, sizeof(fd_set)); + memcpy(&write_set, &test->write_set, sizeof(fd_set)); + (void) gettimeofday(&now, NULL); + timeout = tmr_timeout(&now); + result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout); + if (result < 0 && errno != EINTR) { + i_errno = IESELECT; + return -1; + } + if (result > 0) { + if (FD_ISSET(test->ctrl_sck, &read_set)) { + if (iperf_handle_message_client(test) < 0) { + return -1; } + FD_CLR(test->ctrl_sck, &read_set); } } @@ -395,26 +380,10 @@ iperf_run_client(struct iperf_test * test) /* Is this our first time really running? */ if (startup) { startup = 0; - /* Decide which concurrency model to use for the real test. - ** SIGALRM is less overhead but there are a bunch of cases - ** where it either won't work or is ill-advised. - */ - if (test->may_use_sigalrm && test->settings->rate == 0 && - (test->stats_interval == 0 || test->stats_interval > 0.2) && - (test->reporter_interval == 0 || test->reporter_interval > 0.2) && - (test->omit == 0 || test->omit > 0.2) && - ! test->reverse) { - concurrency_model = cm_itimer; - test->multisend = 1; - signal(SIGALRM, sigalrm_handler); - sigalrm_triggered = 0; - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 100000; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 100000; - (void) setitimer(ITIMER_REAL, &itv, NULL); - } + SLIST_FOREACH(sp, &test->streams, streams) { + setnonblocking(sp->socket, 1); + } } if (test->reverse) { @@ -423,41 +392,30 @@ iperf_run_client(struct iperf_test * test) return -1; } else { // Regular mode. Client sends. - if (iperf_send(test, concurrency_model == cm_itimer ? NULL : &write_set) < 0) + if (iperf_send(test, &write_set) < 0) return -1; } - if ((concurrency_model == cm_select && - (result == 0 || - (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0))) || - (concurrency_model == cm_itimer && sigalrm_triggered)) { - /* Run the timers. */ - (void) gettimeofday(&now, NULL); - tmr_run(&now); - if (concurrency_model == cm_itimer) - sigalrm_triggered = 0; - } + /* Run the timers. */ + (void) gettimeofday(&now, NULL); + tmr_run(&now); /* Is the test done yet? */ if ((!test->omitting) && ((test->duration != 0 && test->done) || (test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes) || (test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks))) { + + SLIST_FOREACH(sp, &test->streams, streams) { + setnonblocking(sp->socket, 0); + } + /* Yes, done! Send TEST_END. */ test->done = 1; cpu_util(test->cpu_util); test->stats_callback(test); if (iperf_set_send_state(test, TEST_END) != 0) return -1; - /* If we were doing setitimer(), go back to select() for the end. */ - if (concurrency_model == cm_itimer) { - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 0; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 0; - (void) setitimer(ITIMER_REAL, &itv, NULL); - concurrency_model = cm_select; - } } } // If we're in reverse mode, continue draining the data diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c index 6d8d940..e522ca6 100644 --- a/src/iperf_server_api.c +++ b/src/iperf_server_api.c @@ -516,6 +516,8 @@ iperf_run_server(struct iperf_test *test) FD_SET(s, &test->read_set); if (s > test->max_fd) test->max_fd = s; + setnonblocking(s, 1); + streams_accepted++; if (test->on_new_stream) test->on_new_stream(sp); diff --git a/src/main.c b/src/main.c index e0e2a39..d01994e 100644 --- a/src/main.c +++ b/src/main.c @@ -79,9 +79,6 @@ main(int argc, char **argv) iperf_errexit(NULL, "create new test error - %s", iperf_strerror(i_errno)); iperf_defaults(test); /* sets defaults */ - /* This main program doesn't use SIGALRM, so the iperf API may use it. */ - iperf_set_test_may_use_sigalrm(test, 1); - if (iperf_parse_arguments(test, argc, argv) < 0) { iperf_err(test, "parameter error - %s", iperf_strerror(i_errno)); fprintf(stderr, "\n"); diff --git a/src/net.c b/src/net.c index 67e19f0..88e680a 100644 --- a/src/net.c +++ b/src/net.c @@ -171,8 +171,8 @@ Nread(int fd, char *buf, size_t count, int prot) while (nleft > 0) { r = read(fd, buf, nleft); if (r < 0) { - if (errno == EINTR) - r = 0; + if (errno == EINTR || errno == EAGAIN) + break; else return NET_HARDERROR; } else if (r == 0) @@ -200,9 +200,9 @@ Nwrite(int fd, const char *buf, size_t count, int prot) if (r < 0) { switch (errno) { case EINTR: + case EAGAIN: return count - nleft; - case EAGAIN: case ENOBUFS: return NET_SOFTERROR; @@ -271,9 +271,9 @@ Nsendfile(int fromfd, int tofd, const char *buf, size_t count) if (r < 0) { switch (errno) { case EINTR: + case EAGAIN: return count - nleft; - case EAGAIN: case ENOBUFS: case ENOMEM: return NET_SOFTERROR;