Mercurial > dovecot > core-2.2
changeset 18875:3ae8cf3f8320
fts-tika: Fixed crashes when indexing larger attachments with fts-solr.
We were mixing ioloops without switching back to the original ioloop in the
middle. Also io_remove() at deinit caused another timeout to be added, so
this needs to be done while original ioloop is active or we'll just leak the
just-added timeout in io_loop_destroy() and crash later.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 17 Jun 2015 13:12:37 +0300 |
parents | 343602625064 |
children | fec87fb9b071 |
files | src/plugins/fts/fts-parser-tika.c |
diffstat | 1 files changed, 19 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/src/plugins/fts/fts-parser-tika.c Wed Jun 17 12:22:17 2015 +0300 +++ b/src/plugins/fts/fts-parser-tika.c Wed Jun 17 13:12:37 2015 +0300 @@ -148,6 +148,7 @@ struct message_block *block) { struct tika_fts_parser *parser = (struct tika_fts_parser *)_parser; + struct ioloop *prev_ioloop = current_ioloop; const unsigned char *data; size_t size; ssize_t ret; @@ -174,10 +175,11 @@ return; i_assert(parser->payload != NULL); } - /* continue returning data from Tika */ + /* continue returning data from Tika. we'll create a new ioloop just + for reading this one payload. */ while ((ret = i_stream_read_data(parser->payload, &data, &size, 0)) == 0) { if (parser->failed) - return; + break; /* wait for more input from Tika */ if (parser->ioloop == NULL) { parser->ioloop = io_loop_create(); @@ -188,7 +190,12 @@ } io_loop_run(current_ioloop); } - if (size > 0) { + /* switch back to original ioloop. */ + io_loop_set_current(prev_ioloop); + + if (parser->failed) + ; + else if (size > 0) { i_assert(ret > 0); block->data = data; block->size = size; @@ -210,16 +217,18 @@ struct tika_fts_parser *parser = (struct tika_fts_parser *)_parser; int ret = parser->failed ? -1 : 0; + /* remove io before unrefing payload - otherwise lib-http adds another + timeout to ioloop unnecessarily */ + if (parser->payload != NULL) + i_stream_unref(&parser->payload); + if (parser->io != NULL) + io_remove(&parser->io); + if (parser->http_req != NULL) + http_client_request_abort(&parser->http_req); if (parser->ioloop != NULL) { - io_remove(&parser->io); + io_loop_set_current(parser->ioloop); io_loop_destroy(&parser->ioloop); } - if (parser->payload != NULL) - i_stream_unref(&parser->payload); - /* FIXME: kludgy, http_req should be NULL here if we don't want to - free it. requires lib-http changes. */ - if (parser->http_req != NULL) - http_client_request_abort(&parser->http_req); i_free(parser); return ret; }