summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Porzelt <tp@cryosphere.de>2009-09-11 12:09:54 +0200
committerThomas Porzelt <tp@cryosphere.de>2009-09-11 12:09:54 +0200
commit9df7f495ccdde85b8ececb67a5c16852818b03bd (patch)
treebd5b8f4a0e1ec6d4d41b63a3f948f4dbb5f2518f
parent20738ad07967a6f01c743c7dbfdfab30a037781d (diff)
downloadweighttp-9df7f495ccdde85b8ececb67a5c16852818b03bd.tar.gz
weighttp-9df7f495ccdde85b8ececb67a5c16852818b03bd.zip
fix integer overflows with commandline parameters resulting in wrong amount of requests performed
fix client state machine
-rw-r--r--TODO1
-rw-r--r--src/client.c22
-rw-r--r--src/weighttp.c30
3 files changed, 37 insertions, 16 deletions
diff --git a/TODO b/TODO
index ced926e..f009e84 100644
--- a/TODO
+++ b/TODO
@@ -4,3 +4,4 @@
- ssl support
- better error reporting
- ipv6 support
+- progress output
diff --git a/src/client.c b/src/client.c
index c58f650..098cca4 100644
--- a/src/client.c
+++ b/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 */
diff --git a/src/weighttp.c b/src/weighttp.c
index e492045..565564c 100644
--- a/src/weighttp.c
+++ b/src/weighttp.c
@@ -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);