From d742bb4728447bd3b23f43de586343b319c03da0 Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Tue, 1 Jan 2008 13:47:50 +0000 Subject: [PATCH] New 'new_max' configuration bounds the number of tracks that 'new' will return. Previously a new installation with many tracks would attempt to return thousands of tracks, busting event.c's buffer limit. Organization: Straylight/Edgeware From: Richard Kettlewell Made event.c buffer connection abandonment reporting less chatty. --- doc/disorder_config.5.in | 4 ++++ doc/disorder_protocol.5.in | 3 ++- lib/configuration.c | 2 ++ lib/configuration.h | 3 +++ lib/event.c | 26 ++++++++++++++++++-------- server/server.c | 11 ++++++++++- 6 files changed, 39 insertions(+), 10 deletions(-) diff --git a/doc/disorder_config.5.in b/doc/disorder_config.5.in index a2e6383..3b2e5a9 100644 --- a/doc/disorder_config.5.in +++ b/doc/disorder_config.5.in @@ -442,6 +442,10 @@ namepart artist "/([^/]+)/[^/]+/[^/]+$" $1 * namepart ext "(\\.[a-zA-Z0-9]+)$" $1 * .fi .TP +.B new_max \fIMAX\fR +The maximum number of tracks to list when reporting newly noticed tracks. The +default is 100. +.TP .B nice_rescan \fIPRIORITY\fR Set the recan subprocess priority. The default is 10. .IP diff --git a/doc/disorder_protocol.5.in b/doc/disorder_protocol.5.in index 7cb69a7..2d2d644 100644 --- a/doc/disorder_protocol.5.in +++ b/doc/disorder_protocol.5.in @@ -148,7 +148,8 @@ depending on how the tracks came to be added to the queue. .TP .B new \fR[\fIMAX\fR] Send the most recently added \fIMAX\fR tracks in a response body. If the -argument is ommitted, all recently added tracks are listed. +argument is ommitted, the \fBnew_max\fR most recent tracks are listed (see +\fBdisorder_config\fR(5)). .TP .B nop Do nothing. Used by diff --git a/lib/configuration.c b/lib/configuration.c index 3cf276e..67f4f89 100644 --- a/lib/configuration.c +++ b/lib/configuration.c @@ -946,6 +946,7 @@ static const struct conf conf[] = { { C(multicast_loop), &type_boolean, validate_any }, { C(multicast_ttl), &type_integer, validate_non_negative }, { C(namepart), &type_namepart, validate_any }, + { C(new_max), &type_integer, validate_positive }, { C2(nice, nice_rescan), &type_integer, validate_non_negative }, { C(nice_rescan), &type_integer, validate_non_negative }, { C(nice_server), &type_integer, validate_any }, @@ -1188,6 +1189,7 @@ static struct config *config_default(void) { c->cookie_login_lifetime = 86400; c->cookie_key_lifetime = 86400 * 7; c->smtp_server = xstrdup("127.0.0.1"); + c->new_max = 100; /* Default stopwords */ if(config_set(&cs, (int)NDEFAULT_STOPWORDS, (char **)default_stopwords)) exit(1); diff --git a/lib/configuration.h b/lib/configuration.h index f965bbd..aa0682d 100644 --- a/lib/configuration.h +++ b/lib/configuration.h @@ -261,6 +261,9 @@ struct config { /** @brief Origin address for outbound mail */ char *mail_sender; + + /** @brief Maximum number of tracks in response to 'new' */ + long new_max; /* derived values: */ int nparts; /* number of distinct name parts */ diff --git a/lib/event.c b/lib/event.c index 3618bf4..d3a0c33 100644 --- a/lib/event.c +++ b/lib/event.c @@ -930,6 +930,9 @@ struct ev_writer { /** @brief Tied reader or 0 */ ev_reader *reader; + + /** @brief Set when abandoned */ + int abandoned; }; /** @brief State structure for a buffered reader */ @@ -998,9 +1001,12 @@ static int writer_timebound_exceeded(ev_source *ev, void *u) { ev_writer *const w = u; - error(0, "abandoning writer %s because no writes within %ds", - w->what, w->timebound); - w->error = ETIMEDOUT; + if(!w->abandoned) { + w->abandoned = 1; + error(0, "abandoning writer '%s' because no writes within %ds", + w->what, w->timebound); + w->error = ETIMEDOUT; + } return writer_shutdown(ev, now, u); } @@ -1075,11 +1081,15 @@ static int ev_writer_write(struct sink *sk, const void *s, int n) { /* The new buffer contents will exceed the space bound. We assume that the * remote client has gone away and TCP hasn't noticed yet, or that it's got * hopelessly stuck. */ - error(0, "abandoning writer %s because buffer has reached %td bytes", - w->what, w->b.end - w->b.start); - ev_fd_disable(w->ev, ev_write, w->fd); - w->error = EPIPE; - return ev_timeout(w->ev, 0, 0, writer_shutdown, w); + if(!w->abandoned) { + w->abandoned = 1; + error(0, "abandoning writer '%s' because buffer has reached %td bytes", + w->what, w->b.end - w->b.start); + ev_fd_disable(w->ev, ev_write, w->fd); + w->error = EPIPE; + return ev_timeout(w->ev, 0, 0, writer_shutdown, w); + } else + return 0; } /* Make sure there is space */ buffer_space(&w->b, n); diff --git a/server/server.c b/server/server.c index a7dee99..69129c9 100644 --- a/server/server.c +++ b/server/server.c @@ -995,9 +995,18 @@ static int c_nop(struct conn *c, static int c_new(struct conn *c, char **vec, int nvec) { - char **tracks = trackdb_new(0, nvec > 0 ? atoi(vec[0]) : INT_MAX); + int max, n; + char **tracks; + if(nvec > 0) + max = atoi(vec[0]); + else + max = INT_MAX; + if(max <= 0 || max > config->new_max) + max = config->new_max; + tracks = trackdb_new(0, max); sink_printf(ev_writer_sink(c->w), "253 New track list follows\n"); + n = 0; while(*tracks) { sink_printf(ev_writer_sink(c->w), "%s%s\n", **tracks == '.' ? "." : "", *tracks); -- [mdw]