fix integer overflows with commandline parameters resulting in wrong amount of requests performed
fix client state machine
This commit is contained in:
parent
20738ad079
commit
9df7f495cc
1
TODO
1
TODO
@ -4,3 +4,4 @@
|
|||||||
- ssl support
|
- ssl support
|
||||||
- better error reporting
|
- better error reporting
|
||||||
- ipv6 support
|
- ipv6 support
|
||||||
|
- progress output
|
||||||
|
22
src/client.c
22
src/client.c
@ -83,19 +83,18 @@ void client_free(Client *client) {
|
|||||||
static void client_reset(Client *client) {
|
static void client_reset(Client *client) {
|
||||||
//printf("keep alive: %d\n", client->keepalive);
|
//printf("keep alive: %d\n", client->keepalive);
|
||||||
if (!client->keepalive) {
|
if (!client->keepalive) {
|
||||||
ev_io_stop(client->worker->loop, &client->sock_watcher);
|
|
||||||
|
|
||||||
if (client->sock_watcher.fd != -1) {
|
if (client->sock_watcher.fd != -1) {
|
||||||
|
ev_io_stop(client->worker->loop, &client->sock_watcher);
|
||||||
shutdown(client->sock_watcher.fd, SHUT_WR);
|
shutdown(client->sock_watcher.fd, SHUT_WR);
|
||||||
close(client->sock_watcher.fd);
|
close(client->sock_watcher.fd);
|
||||||
|
client->sock_watcher.fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
client->sock_watcher.fd = -1;
|
|
||||||
client->state = CLIENT_START;
|
client->state = CLIENT_START;
|
||||||
} else {
|
} else {
|
||||||
client_set_events(client, EV_WRITE);
|
client_set_events(client, EV_WRITE);
|
||||||
client->worker->stats.req_started++;
|
|
||||||
client->state = CLIENT_WRITING;
|
client->state = CLIENT_WRITING;
|
||||||
|
client->worker->stats.req_started++;
|
||||||
}
|
}
|
||||||
|
|
||||||
client->parser_state = PARSER_START;
|
client->parser_state = PARSER_START;
|
||||||
@ -158,12 +157,16 @@ void client_state_machine(Client *client) {
|
|||||||
//printf("state: %d\n", client->state);
|
//printf("state: %d\n", client->state);
|
||||||
switch (client->state) {
|
switch (client->state) {
|
||||||
case CLIENT_START:
|
case CLIENT_START:
|
||||||
|
client->worker->stats.req_started++;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
r = socket(config->saddr->ai_family, config->saddr->ai_socktype, config->saddr->ai_protocol);
|
r = socket(config->saddr->ai_family, config->saddr->ai_socktype, config->saddr->ai_protocol);
|
||||||
} while (-1 == r && errno == EINTR);
|
} while (-1 == r && errno == EINTR);
|
||||||
|
|
||||||
if (-1 == r) {
|
if (-1 == r) {
|
||||||
client->state = CLIENT_ERROR;
|
client->state = CLIENT_ERROR;
|
||||||
|
strerror_r(errno, client->buffer, sizeof(client->buffer));
|
||||||
|
W_ERROR("socket() failed: %s (%d)", client->buffer, errno);
|
||||||
goto start;
|
goto start;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,8 +177,6 @@ void client_state_machine(Client *client) {
|
|||||||
ev_io_set(&client->sock_watcher, r, EV_WRITE);
|
ev_io_set(&client->sock_watcher, r, EV_WRITE);
|
||||||
ev_io_start(client->worker->loop, &client->sock_watcher);
|
ev_io_start(client->worker->loop, &client->sock_watcher);
|
||||||
|
|
||||||
client->worker->stats.req_started++;
|
|
||||||
|
|
||||||
if (!client_connect(client)) {
|
if (!client_connect(client)) {
|
||||||
client->state = CLIENT_ERROR;
|
client->state = CLIENT_ERROR;
|
||||||
goto start;
|
goto start;
|
||||||
@ -257,7 +258,6 @@ void client_state_machine(Client *client) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
case CLIENT_ERROR:
|
case CLIENT_ERROR:
|
||||||
//printf("client error\n");
|
//printf("client error\n");
|
||||||
client->worker->stats.req_error++;
|
client->worker->stats.req_error++;
|
||||||
@ -275,9 +275,15 @@ void client_state_machine(Client *client) {
|
|||||||
client->worker->stats.req_failed++;
|
client->worker->stats.req_failed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*if (client->worker->id == 1 && (client->worker->stats.req_started % 10) == 0)
|
||||||
|
printf("thread: %d, requests done: %"PRIu64", %"PRIu64" todo, %"PRIu64" started\n",
|
||||||
|
client->worker->id, client->worker->stats.req_done, client->worker->stats.req_todo,
|
||||||
|
client->worker->stats.req_started);*/
|
||||||
|
|
||||||
if (client->worker->stats.req_started == client->worker->stats.req_todo) {
|
if (client->worker->stats.req_started == client->worker->stats.req_todo) {
|
||||||
/* this worker has started all requests */
|
/* this worker has started all requests */
|
||||||
ev_io_stop(client->worker->loop, &client->sock_watcher);
|
client->keepalive = 0;
|
||||||
|
client_reset(client);
|
||||||
|
|
||||||
if (client->worker->stats.req_done == client->worker->stats.req_todo) {
|
if (client->worker->stats.req_done == client->worker->stats.req_todo) {
|
||||||
/* this worker has finished all requests */
|
/* this worker has finished all requests */
|
||||||
|
@ -139,6 +139,20 @@ static char *forge_request(char *url, char keep_alive, char **host, uint16_t *po
|
|||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t str_to_uint64(char *str) {
|
||||||
|
uint64_t i;
|
||||||
|
|
||||||
|
for (i = 0; *str; str++) {
|
||||||
|
if (*str < '0' || *str > '9')
|
||||||
|
return UINT64_MAX;
|
||||||
|
|
||||||
|
i *= 10;
|
||||||
|
i += *str - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
Worker **workers;
|
Worker **workers;
|
||||||
pthread_t *threads;
|
pthread_t *threads;
|
||||||
@ -179,7 +193,7 @@ int main(int argc, char *argv[]) {
|
|||||||
config.keep_alive = 1;
|
config.keep_alive = 1;
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
config.req_count = atoi(optarg);
|
config.req_count = str_to_uint64(optarg);
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
config.thread_count = atoi(optarg);
|
config.thread_count = atoi(optarg);
|
||||||
@ -220,7 +234,7 @@ int main(int argc, char *argv[]) {
|
|||||||
show_help();
|
show_help();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (config.thread_count > config.req_count || config.thread_count > config.concur_count || config.concur_count > config.req_count) {
|
if (config.req_count == UINT64_MAX || config.thread_count > config.req_count || config.thread_count > config.concur_count || config.concur_count > config.req_count) {
|
||||||
W_ERROR("%s", "insane arguments\n");
|
W_ERROR("%s", "insane arguments\n");
|
||||||
show_help();
|
show_help();
|
||||||
return 1;
|
return 1;
|
||||||
@ -259,9 +273,9 @@ int main(int argc, char *argv[]) {
|
|||||||
stats.ts_start = ev_time();
|
stats.ts_start = ev_time();
|
||||||
|
|
||||||
for (i = 0; i < config.thread_count; i++) {
|
for (i = 0; i < config.thread_count; i++) {
|
||||||
uint16_t reqs = config.req_count / config.thread_count;
|
uint64_t reqs = config.req_count / config.thread_count;
|
||||||
uint16_t concur = config.concur_count / config.thread_count;
|
uint16_t concur = config.concur_count / config.thread_count;
|
||||||
uint16_t diff;
|
uint64_t diff;
|
||||||
|
|
||||||
if (rest_concur) {
|
if (rest_concur) {
|
||||||
diff = (i == config.thread_count) ? rest_concur : (rest_concur / config.thread_count);
|
diff = (i == config.thread_count) ? rest_concur : (rest_concur / config.thread_count);
|
||||||
@ -276,15 +290,15 @@ int main(int argc, char *argv[]) {
|
|||||||
reqs += diff;
|
reqs += diff;
|
||||||
rest_req -= diff;
|
rest_req -= diff;
|
||||||
}
|
}
|
||||||
|
printf("spawning thread #%d: %"PRIu16" concurrent requests, %"PRIu64" total requests\n", i+1, concur, reqs);
|
||||||
|
workers[i] = worker_new(i+1, &config, concur, reqs);
|
||||||
|
|
||||||
workers[i] = worker = worker_new(i+1, &config, concur, reqs);
|
if (!(workers[i])) {
|
||||||
|
|
||||||
if (!worker) {
|
|
||||||
W_ERROR("%s", "failed to allocate worker or client");
|
W_ERROR("%s", "failed to allocate worker or client");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = pthread_create(&threads[i], NULL, worker_thread, (void*)worker);
|
err = pthread_create(&threads[i], NULL, worker_thread, (void*)workers[i]);
|
||||||
|
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
W_ERROR("failed spawning thread (%d)", err);
|
W_ERROR("failed spawning thread (%d)", err);
|
||||||
|
Loading…
Reference in New Issue
Block a user