From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-3.0 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00, T_RP_MATCHES_RCVD shortcircuit=no autolearn=unavailable version=3.3.2 X-Original-To: meta@public-inbox.org Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id ED1101FD21 for ; Wed, 2 Sep 2015 06:59:41 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 1/7] view: close possible race condition in thread view Date: Wed, 2 Sep 2015 06:59:33 +0000 Message-Id: <1441177179-16628-2-git-send-email-e@80x24.org> In-Reply-To: <1441177179-16628-1-git-send-email-e@80x24.org> References: <1441177179-16628-1-git-send-email-e@80x24.org> List-Id: It's possible that the Xapian index and git HEAD can be out-of-sync and a message which existed when we did the search is no longer accessible by the time we get to rendering it. --- lib/PublicInbox/View.pm | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm index 6aa199e..1eb12a9 100644 --- a/lib/PublicInbox/View.pm +++ b/lib/PublicInbox/View.pm @@ -144,7 +144,7 @@ sub emit_thread_html { my $msgs = load_results($res); my $nr = scalar @$msgs; return missing_thread($cb) if $nr == 0; - my $fh = $cb->([200,['Content-Type'=>'text/html; charset=UTF-8']]); + my $orig_cb = $cb; my $th = thread_results($msgs); my $state = { ctx => $ctx, @@ -155,18 +155,23 @@ sub emit_thread_html { { require PublicInbox::GitCatFile; my $git = PublicInbox::GitCatFile->new($ctx->{git_dir}); - thread_entry($fh, $git, $state, $_, 0) for $th->rootset; + thread_entry(\$cb, $git, $state, $_, 0) for $th->rootset; } Email::Address->purge_cache; + + # there could be a race due to a message being deleted in git + # but still being in the Xapian index: + return missing_thread($cb) if ($orig_cb eq $cb); + my $final_anchor = $state->{anchor_idx}; my $next = ""; $next .= $final_anchor == 1 ? 'only message in' : 'end of'; $next .= " thread, back to index\n"; $next .= "download thread: mbox.gz"; $next .= " / follow: Atom feed\n\n"; - $fh->write("
" . PRE_WRAP . $next . $foot . + $cb->write("
" . PRE_WRAP . $next . $foot . ""); - $fh->close; + $cb->close; } sub index_walk { @@ -536,14 +541,16 @@ sub anchor_for { } sub thread_html_head { - my ($mime) = @_; + my ($cb, $mime) = @_; + $$cb = $$cb->([200, ['Content-Type'=> 'text/html; charset=UTF-8']]); + my $s = PublicInbox::Hval->new_oneline($mime->header('Subject')); $s = $s->as_html; - "$s"; + $$cb->write("$s"); } sub thread_entry { - my ($fh, $git, $state, $node, $level) = @_; + my ($cb, $git, $state, $node, $level) = @_; return unless $node; if (my $mime = $node->message) { @@ -552,13 +559,13 @@ sub thread_entry { $mime = eval { Email::MIME->new($git->cat_file("HEAD:$path")) }; if ($mime) { if ($state->{anchor_idx} == 0) { - $fh->write(thread_html_head($mime)); + thread_html_head($cb, $mime); } - index_entry($fh, $mime, $level, $state); + index_entry($$cb, $mime, $level, $state); } } - thread_entry($fh, $git, $state, $node->child, $level + 1); - thread_entry($fh, $git, $state, $node->next, $level); + thread_entry($cb, $git, $state, $node->child, $level + 1); + thread_entry($cb, $git, $state, $node->next, $level); } sub load_results { -- EW