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
|
||||
- better error reporting
|
||||
- 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) {
|
||||
//printf("keep alive: %d\n", client->keepalive);
|
||||
if (!client->keepalive) {
|
||||
ev_io_stop(client->worker->loop, &client->sock_watcher);
|
||||
|
||||
if (client->sock_watcher.fd != -1) {
|
||||
ev_io_stop(client->worker->loop, &client->sock_watcher);
|
||||
shutdown(client->sock_watcher.fd, SHUT_WR);
|
||||
close(client->sock_watcher.fd);
|
||||
client->sock_watcher.fd = -1;
|
||||
}
|
||||
|
||||
client->sock_watcher.fd = -1;
|
||||
client->state = CLIENT_START;
|
||||
} else {
|
||||
client_set_events(client, EV_WRITE);
|
||||
client->worker->stats.req_started++;
|
||||
client->state = CLIENT_WRITING;
|
||||
client->worker->stats.req_started++;
|
||||
}
|
||||
|
||||
client->parser_state = PARSER_START;
|
||||
@ -158,12 +157,16 @@ void client_state_machine(Client *client) {
|
||||
//printf("state: %d\n", client->state);
|
||||
switch (client->state) {
|
||||
case CLIENT_START:
|
||||
client->worker->stats.req_started++;
|
||||
|
||||
do {
|
||||
r = socket(config->saddr->ai_family, config->saddr->ai_socktype, config->saddr->ai_protocol);
|
||||
} while (-1 == r && errno == EINTR);
|
||||
|
||||
if (-1 == r) {
|
||||
client->state = CLIENT_ERROR;
|
||||
strerror_r(errno, client->buffer, sizeof(client->buffer));
|
||||
W_ERROR("socket() failed: %s (%d)", client->buffer, errno);
|
||||
goto start;
|
||||
}
|
||||
|
||||
@ -174,8 +177,6 @@ void client_state_machine(Client *client) {
|
||||
ev_io_set(&client->sock_watcher, r, EV_WRITE);
|
||||
ev_io_start(client->worker->loop, &client->sock_watcher);
|
||||
|
||||
client->worker->stats.req_started++;
|
||||
|
||||
if (!client_connect(client)) {
|
||||
client->state = CLIENT_ERROR;
|
||||
goto start;
|
||||
@ -257,7 +258,6 @@ void client_state_machine(Client *client) {
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case CLIENT_ERROR:
|
||||
//printf("client error\n");
|
||||
client->worker->stats.req_error++;
|
||||
@ -275,9 +275,15 @@ void client_state_machine(Client *client) {
|
||||
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) {
|
||||
/* 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) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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[]) {
|
||||
Worker **workers;
|
||||
pthread_t *threads;
|
||||
@ -179,7 +193,7 @@ int main(int argc, char *argv[]) {
|
||||
config.keep_alive = 1;
|
||||
break;
|
||||
case 'n':
|
||||
config.req_count = atoi(optarg);
|
||||
config.req_count = str_to_uint64(optarg);
|
||||
break;
|
||||
case 't':
|
||||
config.thread_count = atoi(optarg);
|
||||
@ -220,7 +234,7 @@ int main(int argc, char *argv[]) {
|
||||
show_help();
|
||||
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");
|
||||
show_help();
|
||||
return 1;
|
||||
@ -259,9 +273,9 @@ int main(int argc, char *argv[]) {
|
||||
stats.ts_start = ev_time();
|
||||
|
||||
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 diff;
|
||||
uint64_t diff;
|
||||
|
||||
if (rest_concur) {
|
||||
diff = (i == config.thread_count) ? rest_concur : (rest_concur / config.thread_count);
|
||||
@ -276,15 +290,15 @@ int main(int argc, char *argv[]) {
|
||||
reqs += 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 (!worker) {
|
||||
if (!(workers[i])) {
|
||||
W_ERROR("%s", "failed to allocate worker or client");
|
||||
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) {
|
||||
W_ERROR("failed spawning thread (%d)", err);
|
||||
|
Loading…
Reference in New Issue
Block a user