* Transient bucket seems to be working fine in mod_sed.
* Added error handling code so that if ap_pass_brigade fails during
request processing, error is returned to sed_response_filter /
sed_request_filter.
Testing :
* Compiled with 2.2 branch and make sure there is no regression (against gsed
test cases).
* Compiled with trunk.
Final patch is attached.
Regards,
Basant.
On Mon, Sep 15, 2008 at 12:17:04AM -0700, Basant Kukreja wrote:
> Hi,
>
> Attached is the *rough* patch which uses transient buckets in mod_sed output
> filter.
>
> Testing :
> I created a 30MB and 300MB text files and ran OutputSed commands on the
> file.
> * Before the patch, process size (worker mpm with 1 thread) increased up to
> 300M
> for single request. After the patch, process size remains to 3MB to server
> 300M response output.
>
> I also removed 1 extra copying for processing output.
>
> I need to add some more error handling to finalize the patch. Any comments are
> welcome.
>
> Regards,
> Basant.
>
> On Thu, Sep 04, 2008 at 09:47:26PM -0500, William A. Rowe, Jr. wrote:
> > Basant Kukreja wrote:
> >>
> >> Based on your suggestion, I will check what are the other improvements from
> >> mod_substitute can be brought into mod_sed.
> >
> > Note that mod_substitute's brigade handling is already based on the work of
> > both Jim and Nick (author of mod_line_edit) - so they are pretty certain
> > that it is the right approach. Good idea to borrow from it.
> >
> > Bill
> Index: modules/filters/mod_sed.c
> ===================================================================
> --- modules/filters/mod_sed.c (revision 692768)
> +++ modules/filters/mod_sed.c (working copy)
> @@ -26,7 +26,8 @@
> #include "libsed.h"
>
> static const char *sed_filter_name = "Sed";
> -#define MODSED_OUTBUF_SIZE 4000
> +#define MODSED_OUTBUF_SIZE 8000
> +#define MAX_TRANSIENT_BUCKETS 50
>
> typedef struct sed_expr_config
> {
> @@ -44,11 +45,14 @@
> typedef struct sed_filter_ctxt
> {
> sed_eval_t eval;
> + ap_filter_t *f;
> request_rec *r;
> apr_bucket_brigade *bb;
> char *outbuf;
> char *curoutbuf;
> int bufsize;
> + apr_pool_t *tpool;
> + int numbuckets;
> } sed_filter_ctxt;
>
> module AP_MODULE_DECLARE_DATA sed_module;
> @@ -71,29 +75,68 @@
> sed_cfg->last_error = error;
> }
>
> +/* clear the temporary pool (used for transient buckets)
> + */
> +static void clear_ctxpool(sed_filter_ctxt* ctx)
> +{
> + apr_pool_clear(ctx->tpool);
> + ctx->outbuf = NULL;
> + ctx->curoutbuf = NULL;
> + ctx->numbuckets = 0;
> +}
> +
> +/* alloc_outbuf
> + * allocate output buffer
> + */
> +static void alloc_outbuf(sed_filter_ctxt* ctx)
> +{
> + ctx->outbuf = apr_palloc(ctx->tpool, ctx->bufsize + 1);
> + ctx->curoutbuf = ctx->outbuf;
> +}
> +
> +/* append_bucket
> + * Allocate a new bucket from buf and sz and append to ctx->bb
> + */
> +static void append_bucket(sed_filter_ctxt* ctx, char* buf, int sz)
> +{
> + int rv;
> + apr_bucket *b;
> + if (ctx->tpool == ctx->r->pool) {
> + /* We are not using transient bucket */
> + b = apr_bucket_pool_create(buf, sz, ctx->r->pool,
> + ctx->r->connection->bucket_alloc);
> + APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
> + }
> + else {
> + /* We are using transient bucket */
> + b = apr_bucket_transient_create(buf, sz,
> + ctx->r->connection->bucket_alloc);
> + APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
> + ctx->numbuckets++;
> + if (ctx->numbuckets >= MAX_TRANSIENT_BUCKETS) {
> + b = apr_bucket_flush_create(ctx->r->connection->bucket_alloc);
> + APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
> + rv = ap_pass_brigade(ctx->f->next, ctx->bb);
> + apr_brigade_cleanup(ctx->bb);
> + clear_ctxpool(ctx);
> + }
> + }
> +}
> +
> /*
> * flush_output_buffer
> * Flush the output data (stored in ctx->outbuf)
> */
> -static void flush_output_buffer(sed_filter_ctxt *ctx, char* buf, int sz)
> +static void flush_output_buffer(sed_filter_ctxt *ctx)
> {
> int size = ctx->curoutbuf - ctx->outbuf;
> char *out;
> - apr_bucket *b;
> - if (size + sz <= 0)
> + if ((ctx->outbuf == NULL) || (size <=0))
> return;
> - out = apr_palloc(ctx->r->pool, size + sz);
> - if (size) {
> - memcpy(out, ctx->outbuf, size);
> - }
> - if (buf && (sz > 0)) {
> - memcpy(out + size, buf, sz);
> - }
> - /* Reset the output buffer position */
> + out = apr_palloc(ctx->tpool, size);
> + memcpy(out, ctx->outbuf, size);
> + append_bucket(ctx, out, size);
> ctx->curoutbuf = ctx->outbuf;
> - b = apr_bucket_pool_create(out, size + sz, ctx->r->pool,
> - ctx->r->connection->bucket_alloc);
> - APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
> }
>
> /* This is a call back function. When libsed wants to generate the output,
> @@ -104,11 +147,38 @@
> /* dummy is basically filter context. Context is passed during invocation
> * of sed_eval_buffer
> */
> + int remainbytes = 0;
> sed_filter_ctxt *ctx = (sed_filter_ctxt *) dummy;
> - if (((ctx->curoutbuf - ctx->outbuf) + sz) >= ctx->bufsize) {
> - /* flush current buffer */
> - flush_output_buffer(ctx, buf, sz);
> + if (ctx->outbuf == NULL) {
> + alloc_outbuf(ctx);
> }
> + remainbytes = ctx->bufsize - (ctx->curoutbuf - ctx->outbuf);
> + if (sz >= remainbytes) {
> + if (remainbytes > 0) {
> + memcpy(ctx->curoutbuf, buf, remainbytes);
> + buf += remainbytes;
> + sz -= remainbytes;
> + ctx->curoutbuf += remainbytes;
> + }
> + /* buffer is now full */
> + append_bucket(ctx, ctx->outbuf, ctx->bufsize);
> + /* old buffer is now used so allocate new buffer */
> + alloc_outbuf(ctx);
> + /* if size is bigger than the allocated buffer directly add to
> output brigade */
> + if (sz >= ctx->bufsize) {
> + char* newbuf = apr_palloc(ctx->tpool, sz);
> + memcpy(newbuf, buf, sz);
> + append_bucket(ctx, newbuf, sz);
> + /* pool might get clear after append_bucket */
> + if (ctx->outbuf == NULL) {
> + alloc_outbuf(ctx);
> + }
> + }
> + else {
> + memcpy(ctx->curoutbuf, buf, sz);
> + ctx->curoutbuf += sz;
> + }
> + }
> else {
> memcpy(ctx->curoutbuf, buf, sz);
> ctx->curoutbuf += sz;
> @@ -153,10 +223,11 @@
>
> /* Initialize sed filter context. If successful then context is set in f->ctx
> */
> -static apr_status_t init_context(ap_filter_t *f, sed_expr_config *sed_cfg)
> +static apr_status_t init_context(ap_filter_t *f, sed_expr_config *sed_cfg,
> int usetpool)
> {
> apr_status_t status;
> sed_filter_ctxt* ctx;
> + apr_pool_t *tpool;
> request_rec *r = f->r;
> /* Create the context. Call sed_init_eval. libsed will generated
> * output by calling sed_write_output and generates any error by
> @@ -165,6 +236,8 @@
> ctx = apr_pcalloc(r->pool, sizeof(sed_filter_ctxt));
> ctx->r = r;
> ctx->bb = NULL;
> + ctx->numbuckets = 0;
> + ctx->f = f;
> status = sed_init_eval(&ctx->eval, sed_cfg->sed_cmds, log_sed_errf,
> r, &sed_write_output, r->pool);
> if (status != APR_SUCCESS) {
> @@ -173,8 +246,13 @@
> apr_pool_cleanup_register(r->pool, &ctx->eval, sed_eval_cleanup,
> apr_pool_cleanup_null);
> ctx->bufsize = MODSED_OUTBUF_SIZE;
> - ctx->outbuf = apr_palloc(r->pool, ctx->bufsize + 1);
> - ctx->curoutbuf = ctx->outbuf;
> + if (usetpool) {
> + apr_pool_create(&(ctx->tpool), r->pool);
> + }
> + else {
> + ctx->tpool = r->pool;
> + }
> + alloc_outbuf(ctx);
> f->ctx = ctx;
> return APR_SUCCESS;
> }
> @@ -204,10 +282,11 @@
> return ap_pass_brigade(f->next, bb);
> }
>
> - status = init_context(f, sed_cfg);
> + status = init_context(f, sed_cfg, 1);
> if (status != APR_SUCCESS)
> return status;
> ctx = f->ctx;
> + apr_table_unset(f->r->headers_out, "Content-Length");
> }
>
> ctx->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
> @@ -239,7 +318,7 @@
> apr_bucket *b1 = APR_BUCKET_NEXT(b);
> /* Now clean up the internal sed buffer */
> sed_finalize_eval(&ctx->eval, ctx);
> - flush_output_buffer(ctx, NULL, 0);
> + flush_output_buffer(ctx);
> APR_BUCKET_REMOVE(b);
> /* Insert the eos bucket to ctx->bb brigade */
> APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
> @@ -248,12 +327,8 @@
> else if (APR_BUCKET_IS_FLUSH(b)) {
> apr_bucket *b1 = APR_BUCKET_NEXT(b);
> APR_BUCKET_REMOVE(b);
> + flush_output_buffer(ctx);
> APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
> - status = ap_pass_brigade(f->next, ctx->bb);
> - apr_brigade_cleanup(ctx->bb);
> - if (status != APR_SUCCESS) {
> - return status;
> - }
> b = b1;
> }
> else if (APR_BUCKET_IS_METADATA(b)) {
> @@ -264,9 +339,9 @@
> apr_bucket *b1 = APR_BUCKET_NEXT(b);
> status = sed_eval_buffer(&ctx->eval, buf, bytes, ctx);
> if (status != APR_SUCCESS) {
> + clear_ctxpool(ctx);
> return status;
> }
> - flush_output_buffer(ctx, NULL, 0);
> APR_BUCKET_REMOVE(b);
> apr_bucket_delete(b);
> b = b1;
> @@ -278,7 +353,14 @@
> }
> }
> apr_brigade_cleanup(bb);
> - return ap_pass_brigade(f->next, ctx->bb);
> + flush_output_buffer(ctx);
> + status = APR_SUCCESS;
> + if (!APR_BRIGADE_EMPTY(ctx->bb)) {
> + status = ap_pass_brigade(f->next, ctx->bb);
> + apr_brigade_cleanup(ctx->bb);
> + }
> + clear_ctxpool(ctx);
> + return status;
> }
>
> /* Entry function for Sed input filter */
> @@ -309,7 +391,7 @@
> /* XXX : Should we filter the sub requests too */
> return ap_get_brigade(f->next, bb, mode, block, readbytes);
> }
> - status = init_context(f, sed_cfg);
> + status = init_context(f, sed_cfg, 0);
> if (status != APR_SUCCESS)
> return status;
> ctx = f->ctx;
> @@ -352,7 +434,7 @@
> if (APR_BUCKET_IS_EOS(b)) {
> /* eos bucket. Clear the internal sed buffers */
> sed_finalize_eval(&ctx->eval, ctx);
> - flush_output_buffer(ctx, NULL, 0);
> + flush_output_buffer(ctx);
> APR_BUCKET_REMOVE(b);
> APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
> break;
> @@ -366,7 +448,7 @@
> status = sed_eval_buffer(&ctx->eval, buf, bytes, ctx);
> if (status != APR_SUCCESS)
> return status;
> - flush_output_buffer(ctx, NULL, 0);
> + flush_output_buffer(ctx);
> }
> }
> apr_brigade_cleanup(bbinp);
Index: modules/filters/mod_sed.c
===================================================================
--- modules/filters/mod_sed.c (revision 728840)
+++ modules/filters/mod_sed.c (working copy)
@@ -27,6 +27,7 @@
static const char *sed_filter_name = "Sed";
#define MODSED_OUTBUF_SIZE 8000
+#define MAX_TRANSIENT_BUCKETS 50
typedef struct sed_expr_config
{
@@ -44,11 +45,14 @@
typedef struct sed_filter_ctxt
{
sed_eval_t eval;
+ ap_filter_t *f;
request_rec *r;
apr_bucket_brigade *bb;
char *outbuf;
char *curoutbuf;
int bufsize;
+ apr_pool_t *tpool;
+ int numbuckets;
} sed_filter_ctxt;
module AP_MODULE_DECLARE_DATA sed_module;
@@ -56,63 +60,137 @@
/* This function will be call back from libsed functions if there is any error
* happend during execution of sed scripts
*/
-static void log_sed_errf(void *data, const char *error)
+static apr_status_t log_sed_errf(void *data, const char *error)
{
request_rec *r = (request_rec *) data;
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, error);
+ return APR_SUCCESS;
}
/* This function will be call back from libsed functions if there is any
* compilation error.
*/
-static void sed_compile_errf(void *data, const char *error)
+static apr_status_t sed_compile_errf(void *data, const char *error)
{
sed_expr_config *sed_cfg = (sed_expr_config *) data;
sed_cfg->last_error = error;
+ return APR_SUCCESS;
}
+/* clear the temporary pool (used for transient buckets)
+ */
+static void clear_ctxpool(sed_filter_ctxt* ctx)
+{
+ apr_pool_clear(ctx->tpool);
+ ctx->outbuf = NULL;
+ ctx->curoutbuf = NULL;
+ ctx->numbuckets = 0;
+}
+
+/* alloc_outbuf
+ * allocate output buffer
+ */
+static void alloc_outbuf(sed_filter_ctxt* ctx)
+{
+ ctx->outbuf = apr_palloc(ctx->tpool, ctx->bufsize + 1);
+ ctx->curoutbuf = ctx->outbuf;
+}
+
+/* append_bucket
+ * Allocate a new bucket from buf and sz and append to ctx->bb
+ */
+static apr_status_t append_bucket(sed_filter_ctxt* ctx, char* buf, int sz)
+{
+ apr_status_t status = APR_SUCCESS;
+ apr_bucket *b;
+ if (ctx->tpool == ctx->r->pool) {
+ /* We are not using transient bucket */
+ b = apr_bucket_pool_create(buf, sz, ctx->r->pool,
+ ctx->r->connection->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
+ }
+ else {
+ /* We are using transient bucket */
+ b = apr_bucket_transient_create(buf, sz,
+ ctx->r->connection->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
+ ctx->numbuckets++;
+ if (ctx->numbuckets >= MAX_TRANSIENT_BUCKETS) {
+ b = apr_bucket_flush_create(ctx->r->connection->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
+ status = ap_pass_brigade(ctx->f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
+ clear_ctxpool(ctx);
+ }
+ }
+ return status;
+}
+
/*
* flush_output_buffer
* Flush the output data (stored in ctx->outbuf)
*/
-static void flush_output_buffer(sed_filter_ctxt *ctx, char* buf, int sz)
+static apr_status_t flush_output_buffer(sed_filter_ctxt *ctx)
{
int size = ctx->curoutbuf - ctx->outbuf;
char *out;
- apr_bucket *b;
- if (size + sz <= 0)
- return;
- out = apr_palloc(ctx->r->pool, size + sz);
- if (size) {
- memcpy(out, ctx->outbuf, size);
- }
- if (buf && (sz > 0)) {
- memcpy(out + size, buf, sz);
- }
- /* Reset the output buffer position */
+ apr_status_t status = APR_SUCCESS;
+ if ((ctx->outbuf == NULL) || (size <=0))
+ return status;
+ out = apr_palloc(ctx->tpool, size);
+ memcpy(out, ctx->outbuf, size);
+ status = append_bucket(ctx, out, size);
ctx->curoutbuf = ctx->outbuf;
- b = apr_bucket_pool_create(out, size + sz, ctx->r->pool,
- ctx->r->connection->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
+ return status;
}
/* This is a call back function. When libsed wants to generate the output,
* this function will be invoked.
*/
-static void sed_write_output(void *dummy, char *buf, int sz)
+static apr_status_t sed_write_output(void *dummy, char *buf, int sz)
{
/* dummy is basically filter context. Context is passed during invocation
* of sed_eval_buffer
*/
+ int remainbytes = 0;
+ apr_status_t status = APR_SUCCESS;
sed_filter_ctxt *ctx = (sed_filter_ctxt *) dummy;
- if (((ctx->curoutbuf - ctx->outbuf) + sz) >= ctx->bufsize) {
- /* flush current buffer */
- flush_output_buffer(ctx, buf, sz);
+ if (ctx->outbuf == NULL) {
+ alloc_outbuf(ctx);
}
+ remainbytes = ctx->bufsize - (ctx->curoutbuf - ctx->outbuf);
+ if (sz >= remainbytes) {
+ if (remainbytes > 0) {
+ memcpy(ctx->curoutbuf, buf, remainbytes);
+ buf += remainbytes;
+ sz -= remainbytes;
+ ctx->curoutbuf += remainbytes;
+ }
+ /* buffer is now full */
+ status = append_bucket(ctx, ctx->outbuf, ctx->bufsize);
+ /* old buffer is now used so allocate new buffer */
+ alloc_outbuf(ctx);
+ /* if size is bigger than the allocated buffer directly add to output
+ * brigade */
+ if ((status == APR_SUCCESS) && (sz >= ctx->bufsize)) {
+ char* newbuf = apr_palloc(ctx->tpool, sz);
+ memcpy(newbuf, buf, sz);
+ status = append_bucket(ctx, newbuf, sz);
+ /* pool might get clear after append_bucket */
+ if (ctx->outbuf == NULL) {
+ alloc_outbuf(ctx);
+ }
+ }
+ else {
+ memcpy(ctx->curoutbuf, buf, sz);
+ ctx->curoutbuf += sz;
+ }
+ }
else {
memcpy(ctx->curoutbuf, buf, sz);
ctx->curoutbuf += sz;
}
+ return status;
}
/* Compile a sed expression. Compiled context is saved in sed_cfg->sed_cmds.
@@ -153,7 +231,7 @@
/* Initialize sed filter context. If successful then context is set in f->ctx
*/
-static apr_status_t init_context(ap_filter_t *f, sed_expr_config *sed_cfg)
+static apr_status_t init_context(ap_filter_t *f, sed_expr_config *sed_cfg, int
usetpool)
{
apr_status_t status;
sed_filter_ctxt* ctx;
@@ -165,6 +243,8 @@
ctx = apr_pcalloc(r->pool, sizeof(sed_filter_ctxt));
ctx->r = r;
ctx->bb = NULL;
+ ctx->numbuckets = 0;
+ ctx->f = f;
status = sed_init_eval(&ctx->eval, sed_cfg->sed_cmds, log_sed_errf,
r, &sed_write_output, r->pool);
if (status != APR_SUCCESS) {
@@ -173,8 +253,13 @@
apr_pool_cleanup_register(r->pool, &ctx->eval, sed_eval_cleanup,
apr_pool_cleanup_null);
ctx->bufsize = MODSED_OUTBUF_SIZE;
- ctx->outbuf = apr_palloc(r->pool, ctx->bufsize + 1);
- ctx->curoutbuf = ctx->outbuf;
+ if (usetpool) {
+ apr_pool_create(&(ctx->tpool), r->pool);
+ }
+ else {
+ ctx->tpool = r->pool;
+ }
+ alloc_outbuf(ctx);
f->ctx = ctx;
return APR_SUCCESS;
}
@@ -204,10 +289,11 @@
return ap_pass_brigade(f->next, bb);
}
- status = init_context(f, sed_cfg);
+ status = init_context(f, sed_cfg, 1);
if (status != APR_SUCCESS)
return status;
ctx = f->ctx;
+ apr_table_unset(f->r->headers_out, "Content-Length");
}
ctx->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
@@ -239,7 +325,11 @@
apr_bucket *b1 = APR_BUCKET_NEXT(b);
/* Now clean up the internal sed buffer */
sed_finalize_eval(&ctx->eval, ctx);
- flush_output_buffer(ctx, NULL, 0);
+ status = flush_output_buffer(ctx);
+ if (status != APR_SUCCESS) {
+ clear_ctxpool(ctx);
+ return status;
+ }
APR_BUCKET_REMOVE(b);
/* Insert the eos bucket to ctx->bb brigade */
APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
@@ -248,12 +338,12 @@
else if (APR_BUCKET_IS_FLUSH(b)) {
apr_bucket *b1 = APR_BUCKET_NEXT(b);
APR_BUCKET_REMOVE(b);
- APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
- status = ap_pass_brigade(f->next, ctx->bb);
- apr_brigade_cleanup(ctx->bb);
+ status = flush_output_buffer(ctx);
if (status != APR_SUCCESS) {
+ clear_ctxpool(ctx);
return status;
}
+ APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
b = b1;
}
else if (APR_BUCKET_IS_METADATA(b)) {
@@ -264,9 +354,9 @@
apr_bucket *b1 = APR_BUCKET_NEXT(b);
status = sed_eval_buffer(&ctx->eval, buf, bytes, ctx);
if (status != APR_SUCCESS) {
+ clear_ctxpool(ctx);
return status;
}
- flush_output_buffer(ctx, NULL, 0);
APR_BUCKET_REMOVE(b);
apr_bucket_delete(b);
b = b1;
@@ -278,7 +368,17 @@
}
}
apr_brigade_cleanup(bb);
- return ap_pass_brigade(f->next, ctx->bb);
+ status = flush_output_buffer(ctx);
+ if (status != APR_SUCCESS) {
+ clear_ctxpool(ctx);
+ return status;
+ }
+ if (!APR_BRIGADE_EMPTY(ctx->bb)) {
+ status = ap_pass_brigade(f->next, ctx->bb);
+ apr_brigade_cleanup(ctx->bb);
+ }
+ clear_ctxpool(ctx);
+ return status;
}
/* Entry function for Sed input filter */
@@ -309,7 +409,7 @@
/* XXX : Should we filter the sub requests too */
return ap_get_brigade(f->next, bb, mode, block, readbytes);
}
- status = init_context(f, sed_cfg);
+ status = init_context(f, sed_cfg, 0);
if (status != APR_SUCCESS)
return status;
ctx = f->ctx;
@@ -352,7 +452,7 @@
if (APR_BUCKET_IS_EOS(b)) {
/* eos bucket. Clear the internal sed buffers */
sed_finalize_eval(&ctx->eval, ctx);
- flush_output_buffer(ctx, NULL, 0);
+ flush_output_buffer(ctx);
APR_BUCKET_REMOVE(b);
APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
break;
@@ -366,7 +466,7 @@
status = sed_eval_buffer(&ctx->eval, buf, bytes, ctx);
if (status != APR_SUCCESS)
return status;
- flush_output_buffer(ctx, NULL, 0);
+ flush_output_buffer(ctx);
}
}
apr_brigade_cleanup(bbinp);
Index: modules/filters/sed1.c
===================================================================
--- modules/filters/sed1.c (revision 728840)
+++ modules/filters/sed1.c (working copy)
@@ -71,8 +71,8 @@
static char *place(sed_eval_t *eval, char *asp, char *al1, char *al2);
static apr_status_t command(sed_eval_t *eval, sed_reptr_t *ipc,
step_vars_storage *step_vars);
-static void wline(sed_eval_t *eval, char *buf, int sz);
-static void arout(sed_eval_t *eval);
+static apr_status_t wline(sed_eval_t *eval, char *buf, int sz);
+static apr_status_t arout(sed_eval_t *eval);
static void eval_errf(sed_eval_t *eval, const char *fmt, ...)
{
@@ -370,8 +370,8 @@
eval->lspend--;
*eval->lspend = '\0';
rv = execute(eval);
- if (rv != 0)
- return APR_EGENERAL;
+ if (rv != APR_SUCCESS)
+ return rv;
}
while (bufsz) {
@@ -396,8 +396,8 @@
buf += (llen + 1);
bufsz -= (llen + 1);
rv = execute(eval);
- if (rv != 0)
- return APR_EGENERAL;
+ if (rv != APR_SUCCESS)
+ return rv;
if (eval->quitflag)
break;
}
@@ -440,8 +440,8 @@
*eval->lspend = '\0';
rv = execute(eval);
- if (rv != 0)
- return APR_EGENERAL;
+ if (rv != APR_SUCCESS)
+ return rv;
}
eval->quitflag = 1;
@@ -456,6 +456,7 @@
{
sed_reptr_t *ipc = eval->commands->ptrspace;
step_vars_storage step_vars;
+ apr_status_t rv = APR_SUCCESS;
eval->lnum++;
@@ -471,7 +472,6 @@
while (ipc->command) {
char *p1;
char *p2;
- apr_status_t rv;
int c;
p1 = ipc->ad1;
@@ -554,17 +554,20 @@
ipc = ipc->next;
}
- if (!eval->commands->nflag && !eval->delflag)
- wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
+ if (!eval->commands->nflag && !eval->delflag) {
+ rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
if (eval->aptr > eval->abuf)
- arout(eval);
+ rv = arout(eval);
eval->delflag = 0;
eval->lspend = eval->linebuf;
- return APR_SUCCESS;
+ return rv;
}
/*
@@ -686,6 +689,7 @@
char *p1, *p2, *p3;
int length;
char sz[32]; /* 32 bytes enough to store 64 bit integer in decimal */
+ apr_status_t rv = APR_SUCCESS;
switch(ipc->command) {
@@ -704,7 +708,7 @@
if(!eval->inar[ipc->nrep] || eval->dolflag) {
for (p1 = ipc->re1; *p1; p1++)
;
- wline(eval, ipc->re1, p1 - ipc->re1);
+ rv = wline(eval, ipc->re1, p1 - ipc->re1);
}
break;
case DCOM:
@@ -727,7 +731,7 @@
case EQCOM:
length = apr_snprintf(sz, sizeof(sz), "%d", (int) eval->lnum);
- wline(eval, sz, length);
+ rv = wline(eval, sz, length);
break;
case GCOM:
@@ -750,7 +754,7 @@
case ICOM:
for (p1 = ipc->re1; *p1; p1++);
- wline(eval, ipc->re1, p1 - ipc->re1);
+ rv = wline(eval, ipc->re1, p1 - ipc->re1);
break;
case BCOM:
@@ -769,8 +773,10 @@
while ((*p2++ = *p3++) != 0)
if(p2 >= eval->lcomend) {
*p2 = '\\';
- wline(eval, eval->genbuf,
- strlen(eval->genbuf));
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
p2 = eval->genbuf;
}
p2--;
@@ -781,32 +787,47 @@
*p2++ = '\\';
if(p2 >= eval->lcomend) {
*p2 = '\\';
- wline(eval, eval->genbuf, strlen(eval->genbuf));
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
p2 = eval->genbuf;
}
*p2++ = (*p1 >> 6) + '0';
if(p2 >= eval->lcomend) {
*p2 = '\\';
- wline(eval, eval->genbuf, strlen(eval->genbuf));
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
p2 = eval->genbuf;
}
*p2++ = ((*p1 >> 3) & 07) + '0';
if(p2 >= eval->lcomend) {
*p2 = '\\';
- wline(eval, eval->genbuf, strlen(eval->genbuf));
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
p2 = eval->genbuf;
}
*p2++ = (*p1++ & 07) + '0';
if(p2 >= eval->lcomend) {
*p2 = '\\';
- wline(eval, eval->genbuf, strlen(eval->genbuf));
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
p2 = eval->genbuf;
}
} else {
*p2++ = *p1++;
if(p2 >= eval->lcomend) {
*p2 = '\\';
- wline(eval, eval->genbuf, strlen(eval->genbuf));
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
p2 = eval->genbuf;
}
}
@@ -815,48 +836,65 @@
while ((*p2++ = *p3++) != 0)
if(p2 >= eval->lcomend) {
*p2 = '\\';
- wline(eval, eval->genbuf, strlen(eval->genbuf));
+ rv = wline(eval, eval->genbuf,
+ strlen(eval->genbuf));
+ if (rv != APR_SUCCESS)
+ return rv;
p2 = eval->genbuf;
}
p2--;
p1++;
}
*p2 = 0;
- wline(eval, eval->genbuf, strlen(eval->genbuf));
+ rv = wline(eval, eval->genbuf, strlen(eval->genbuf));
break;
case NCOM:
if(!eval->commands->nflag) {
- wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
+ rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
+ if (rv != APR_SUCCESS)
+ return rv;
}
- if(eval->aptr > eval->abuf)
- arout(eval);
+ if(eval->aptr > eval->abuf) {
+ rv = arout(eval);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
eval->lspend = eval->linebuf;
eval->pending = ipc->next;
break;
case CNCOM:
- if(eval->aptr > eval->abuf)
- arout(eval);
+ if(eval->aptr > eval->abuf) {
+ rv = arout(eval);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
append_to_linebuf(eval, "\n");
eval->pending = ipc->next;
break;
case PCOM:
- wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
+ rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
break;
case CPCOM:
for (p1 = eval->linebuf; *p1 != '\n' && *p1 != '\0'; p1++);
- wline(eval, eval->linebuf, p1 - eval->linebuf);
+ rv = wline(eval, eval->linebuf, p1 - eval->linebuf);
break;
case QCOM:
- if (!eval->commands->nflag)
- wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
+ if (!eval->commands->nflag) {
+ rv = wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
+ if (rv != APR_SUCCESS)
+ break;
+ }
- if(eval->aptr > eval->abuf)
- arout(eval);
+ if(eval->aptr > eval->abuf) {
+ rv = arout(eval);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
eval->quitflag = 1;
break;
@@ -876,10 +914,15 @@
}
if(ipc->pfl && eval->commands->nflag && i) {
if(ipc->pfl == 1) {
- wline(eval, eval->linebuf, eval->lspend - eval->linebuf);
+ rv = wline(eval, eval->linebuf, eval->lspend -
+ eval->linebuf);
+ if (rv != APR_SUCCESS)
+ return rv;
} else {
for (p1 = eval->linebuf; *p1 != '\n' && *p1 != '\0'; p1++);
- wline(eval, eval->linebuf, p1 - eval->linebuf);
+ rv = wline(eval, eval->linebuf, p1 - eval->linebuf);
+ if (rv != APR_SUCCESS)
+ return rv;
}
}
if (i && (ipc->findex >= 0) && eval->fcode[ipc->findex])
@@ -910,21 +953,24 @@
while((*p1 = p2[(unsigned char)*p1]) != 0) p1++;
break;
}
- return APR_SUCCESS;
+ return rv;
}
/*
* arout
*/
-static void arout(sed_eval_t *eval)
+static apr_status_t arout(sed_eval_t *eval)
{
+ apr_status_t rv = APR_SUCCESS;
eval->aptr = eval->abuf - 1;
while (*++eval->aptr) {
if ((*eval->aptr)->command == ACOM) {
char *p1;
for (p1 = (*eval->aptr)->re1; *p1; p1++);
- wline(eval, (*eval->aptr)->re1, p1 - (*eval->aptr)->re1);
+ rv = wline(eval, (*eval->aptr)->re1, p1 - (*eval->aptr)->re1);
+ if (rv != APR_SUCCESS)
+ return rv;
} else {
apr_file_t *fi = NULL;
char buf[512];
@@ -936,7 +982,11 @@
while ((apr_file_read(fi, buf, &n)) == APR_SUCCESS) {
if (n == 0)
break;
- eval->writefn(eval->fout, buf, n);
+ rv = eval->writefn(eval->fout, buf, n);
+ if (rv != APR_SUCCESS) {
+ apr_file_close(fi);
+ return rv;
+ }
n = sizeof(buf);
}
apr_file_close(fi);
@@ -944,14 +994,19 @@
}
eval->aptr = eval->abuf;
*eval->aptr = NULL;
+ return rv;
}
/*
* wline
*/
-static void wline(sed_eval_t *eval, char *buf, int sz)
+static apr_status_t wline(sed_eval_t *eval, char *buf, int sz)
{
- eval->writefn(eval->fout, buf, sz);
- eval->writefn(eval->fout, "\n", 1);
+ apr_status_t rv = APR_SUCCESS;
+ rv = eval->writefn(eval->fout, buf, sz);
+ if (rv != APR_SUCCESS)
+ return rv;
+ rv = eval->writefn(eval->fout, "\n", 1);
+ return rv;
}
Index: modules/filters/libsed.h
===================================================================
--- modules/filters/libsed.h (revision 728840)
+++ modules/filters/libsed.h (working copy)
@@ -62,8 +62,8 @@
sed_reptr_t *address;
};
-typedef void (sed_err_fn_t)(void *data, const char *error);
-typedef void (sed_write_fn_t)(void *ctx, char *buf, int sz);
+typedef apr_status_t (sed_err_fn_t)(void *data, const char *error);
+typedef apr_status_t (sed_write_fn_t)(void *ctx, char *buf, int sz);
typedef struct sed_commands_s sed_commands_t;
#define NWFILES 11 /* 10 plus one for standard output */