ovdb bug squashed
Heath Kehoe
hakehoe at avalon.net
Tue Feb 17 21:49:42 UTC 2004
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
format=flowed
I found a pretty significant bug in ovdb, that causes a deadlock that
usually happens during an expireover run, but is actually caused when
an nnrpd exits without closing an opened OVsearch handle (which can
happen if the client disconnects during an XOVER).
Anyone running ovdb needs this fix. It will hopefully appear in the
CURRENT and STABLE trees soon. Also, attached a patch that can be
applied to 2.4.1 (maybe 2.4.0 also, I didn't test that).
-heath
-- Attached file included as plaintext by Ecartis --
-- File: diff.txt
diff -ru ../inn-2.4.1-dist/frontends/ovdb_server.c ./frontends/ovdb_server.c
--- ../inn-2.4.1-dist/frontends/ovdb_server.c 2004-01-07 16:47:19.000000000 -0600
+++ ./frontends/ovdb_server.c 2004-02-17 14:53:13.000000000 -0600
@@ -67,6 +67,7 @@
int bufpos;
void *buf;
time_t lastactive;
+ void *currentsearch;
};
static struct reader *readertab;
@@ -172,11 +173,17 @@
/*syslog(LOG_DEBUG, "OVDB: rs: do_opensrch '%s' %d %d", group, cmd->artlo, cmd->arthi);*/
- reply->handle = ovdb_opensearch(group, cmd->artlo, cmd->arthi);
- if(reply->handle == NULL) {
- reply->status = CMD_OPENSRCH | RPLY_ERROR;
+ if(r->currentsearch != NULL) {
+ /* can only open one search at a time */
+ reply->status = CMD_OPENSRCH | RPLY_ERROR;
} else {
- reply->status = CMD_OPENSRCH;
+ reply->handle = ovdb_opensearch(group, cmd->artlo, cmd->arthi);
+ if(reply->handle == NULL) {
+ reply->status = CMD_OPENSRCH | RPLY_ERROR;
+ } else {
+ reply->status = CMD_OPENSRCH;
+ }
+ r->currentsearch = reply->handle;
}
free(r->buf);
r->buf = reply;
@@ -226,6 +233,7 @@
r->buf = NULL;
r->bufpos = r->buflen = 0;
r->mode = MODE_READ;
+ r->currentsearch = NULL;
}
static void
@@ -370,12 +378,17 @@
newclient(int fd)
{
struct reader *r;
+ int i;
nonblocking(fd, 1);
if(numreaders >= readertablen) {
readertablen += 50;
readertab = xrealloc(readertab, readertablen * sizeof(struct reader));
+ for(i = numreaders; i < readertablen; i++) {
+ readertab[i].mode = MODE_CLOSED;
+ readertab[i].buf = NULL;
+ }
}
r = &(readertab[numreaders]);
@@ -387,6 +400,7 @@
r->bufpos = 0;
r->buf = xstrdup(OVDB_SERVER_BANNER);
r->lastactive = now;
+ r->currentsearch = NULL;
handle_write(r);
}
@@ -403,6 +417,10 @@
if(r->buf != NULL) {
free(r->buf);
}
+ if(r->currentsearch != NULL) {
+ ovdb_closesearch(r->currentsearch);
+ r->currentsearch = NULL;
+ }
/* numreaders will get decremented by the calling function */
for(i = which; i < numreaders-1; i++)
diff -ru ../inn-2.4.1-dist/storage/ovdb/ovdb.c ./storage/ovdb/ovdb.c
--- ../inn-2.4.1-dist/storage/ovdb/ovdb.c 2004-01-07 16:47:19.000000000 -0600
+++ ./storage/ovdb/ovdb.c 2004-02-17 15:12:48.000000000 -0600
@@ -1,8 +1,12 @@
/*
* ovdb.c
- * ovdb 2.00 beta4
- * Overview storage using BerkeleyDB 2.x/3.x
+ * ovdb 2.00
+ * Overview storage using BerkeleyDB 2.x/3.x/4.x
*
+ * 2004-02-17 : Need to track search cursors, since it's possible that
+ * ovdb_closesearch does not get called. We now close
+ * any cursors still open in ovdb_close, or they'd be in
+ * the database indefinitely causing deadlocks.
* 2002-08-13 : Change BOOL to bool, remove portability to < 2.4.
* 2002-08-11 : Cleaned up use of sprintf and fixed a bunch of warnings.
* 2002-02-28 : Update getartinfo for the overview API change in 2.4. This
@@ -212,6 +216,7 @@
if(r < 0 && errno == EINTR)
continue;
syslog(LOG_ERR, "OVDB: rc: cant write: %m");
+ clientfd = -1;
exit(1);
}
p+= r;
@@ -232,6 +237,7 @@
if(r < 0 && errno == EINTR)
continue;
syslog(LOG_ERR, "OVDB: rc: cant read: %m");
+ clientfd = -1;
exit(1);
}
p+= r;
@@ -337,6 +343,7 @@
csend(&rs, sizeof rs);
}
+ clientfd = -1;
}
@@ -1998,6 +2005,13 @@
int state;
};
+/* Even though nnrpd only does one search at a time, a read server process could
+ do many concurrent searches; hence we must keep track of an arbitrary number of
+ open searches */
+static struct ovdbsearch **searches = NULL;
+static int nsearches = 0;
+static int maxsearches = 0;
+
void *ovdb_opensearch(char *group, int low, int high)
{
DB *db;
@@ -2055,6 +2069,18 @@
s->lastart = high;
s->state = 0;
+ if(searches == NULL) {
+ nsearches = 0;
+ maxsearches = 50;
+ searches = xmalloc(sizeof(struct ovdbsearch *) * maxsearches);
+ }
+ if(nsearches == maxsearches) {
+ maxsearches += 50;
+ searches = xrealloc(searches, sizeof(struct ovdbsearch *) * maxsearches);
+ }
+ searches[nsearches] = s;
+ nsearches++;
+
return (void *)s;
}
@@ -2203,6 +2229,7 @@
void ovdb_closesearch(void *handle)
{
+ int i;
if(clientmode) {
struct rs_cmd rs;
@@ -2216,6 +2243,16 @@
if(s->cursor)
s->cursor->c_close(s->cursor);
+ for(i = 0; i < nsearches; i++) {
+ if(s == searches[i]) {
+ break;
+ }
+ }
+ nsearches--;
+ for( ; i < nsearches; i++) {
+ searches[i] = searches[i+1];
+ }
+
free(handle);
}
}
@@ -2813,6 +2850,14 @@
return;
}
+ while(searches != NULL && nsearches) {
+ ovdb_closesearch(searches[0]);
+ }
+ if(searches != NULL) {
+ free(searches);
+ searches = NULL;
+ }
+
if(dbs) {
/* close databases */
for(i = 0; i < ovdb_conf.numdbfiles; i++)
-- Attached file included as plaintext by Ecartis --
-- File: PGP.sig
-- Desc: This is a digitally signed message part
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (Darwin)
iD8DBQFAMox7qvQcDdUKooERAsXTAJ9lGibWFb+EVg05gkppn3KBvBDXyACeJTXV
ncYZaxq9TvOSS6Vo1OgA4DY=
=uo6s
-----END PGP SIGNATURE-----
More information about the inn-workers
mailing list