# HG changeset patch # User Adam Chlipala # Date 1238684100 14400 # Node ID c73c5fe72388452c3d541f7d970f7939ab96be45 # Parent f0224c7f12bbaaf6c9c97f12d67f0ccfc1af23a4 Stop holding client locks throughout request processing diff -r f0224c7f12bb -r c73c5fe72388 src/c/urweb.c --- a/src/c/urweb.c Sun Mar 29 14:13:50 2009 -0400 +++ b/src/c/urweb.c Thu Apr 02 10:55:00 2009 -0400 @@ -99,6 +99,7 @@ int sock; time_t last_contact; unsigned n_channels; + unsigned refcount; } client; @@ -135,6 +136,7 @@ c->last_contact = time(NULL); buf_reset(&c->msgs); c->n_channels = 0; + c->refcount = 0; pthread_mutex_unlock(&c->lock); c->next = clients_used; @@ -145,6 +147,18 @@ return c; } +static void use_client(client *c) { + pthread_mutex_lock(&c->lock); + ++c->refcount; + pthread_mutex_unlock(&c->lock); +} + +static void release_client(client *c) { + pthread_mutex_lock(&c->lock); + --c->refcount; + pthread_mutex_unlock(&c->lock); +} + static const char begin_msgs[] = "HTTP/1.1 200 OK\r\nContent-type: text/plain\r\n\r\n"; static client *find_client(unsigned id) { @@ -222,9 +236,8 @@ return ch; } -static void client_send(int already_locked, client *c, buf *msg) { - if (!already_locked) - pthread_mutex_lock(&c->lock); +static void client_send(client *c, buf *msg) { + pthread_mutex_lock(&c->lock); if (c->sock != -1) { uw_really_send(c->sock, begin_msgs, sizeof(begin_msgs) - 1); @@ -234,8 +247,7 @@ } else buf_append(&c->msgs, msg->start, buf_used(msg)); - if (!already_locked) - pthread_mutex_unlock(&c->lock); + pthread_mutex_unlock(&c->lock); } @@ -472,7 +484,7 @@ if (c == NULL) uw_error(ctx, FATAL, "Unknown client ID in HTTP headers (%s, %s)", id_s, pass_s); else { - pthread_mutex_lock(&c->lock); + use_client(c); ctx->client = c; if (c->mode != USED) @@ -482,7 +494,7 @@ } } else { client *c = new_client(); - pthread_mutex_lock(&c->lock); + use_client(c); ctx->client = c; } } @@ -1847,16 +1859,16 @@ assert (c != NULL && c->mode == USED); - client_send(c == ctx->client, c, &d->msgs); + client_send(c, &d->msgs); } if (ctx->client) - pthread_mutex_unlock(&ctx->client->lock); + release_client(ctx->client); } int uw_rollback(uw_context ctx) { if (ctx->client) - pthread_mutex_unlock(&ctx->client->lock); + release_client(ctx->client); return uw_db_rollback(ctx); } @@ -1891,7 +1903,7 @@ for (c = clients_used; c; c = next) { next = c->next; pthread_mutex_lock(&c->lock); - if (c->last_contact < cutoff) { + if (c->last_contact < cutoff && c->refcount == 0) { failure_kind fk = UNLIMITED_RETRY; if (prev) prev->next = next;