You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2017/07/13 15:46:02 UTC

[couchdb] branch master updated (94f2907 -> 6586102)

This is an automated email from the ASF dual-hosted git repository.

davisp pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


    from 94f2907  Fix couchdb_os_proc_pool eunit timeouts
     new 764168c  Prevent a terrible race condition
     new 6586102  Avoid a race when restarting an index updater

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/couch_index/src/couch_index.erl         | 49 ++++++++++++++++++-----------
 src/couch_index/src/couch_index_updater.erl | 14 +++++++--
 2 files changed, 42 insertions(+), 21 deletions(-)

-- 
To stop receiving notification emails like this one, please contact
['"commits@couchdb.apache.org" <co...@couchdb.apache.org>'].

[couchdb] 02/02: Avoid a race when restarting an index updater

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 6586102ba496e76f27b34794ca11be2712cfa28b
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Wed Jul 12 16:00:33 2017 -0500

    Avoid a race when restarting an index updater
    
    This was encountered during the test suite runs on Travis. It turns out
    that when we restart the indexer its possible to already have the 'EXIT'
    message in our mailbox. When we do we'll then crash with an unknown_info
    error since our updater pid was changed during the restart.
    
    This change simple filters any 'EXIT' message from the old updater from
    the mailbox before restarting thew new index updater.
    
    Fixes #649
---
 src/couch_index/src/couch_index_updater.erl | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/couch_index/src/couch_index_updater.erl b/src/couch_index/src/couch_index_updater.erl
index ad48f40..4f63e9f 100644
--- a/src/couch_index/src/couch_index_updater.erl
+++ b/src/couch_index/src/couch_index_updater.erl
@@ -73,12 +73,20 @@ handle_call({update, IdxState}, _From, #st{idx=Idx, mod=Mod}=State) ->
 handle_call({restart, IdxState}, _From, #st{idx=Idx, mod=Mod}=State) ->
     Args = [Mod:get(db_name, IdxState), Mod:get(idx_name, IdxState)],
     couch_log:info("Restarting index update for db: ~s idx: ~s", Args),
-    case is_pid(State#st.pid) of
+    Pid = State#st.pid,
+    case is_pid(Pid) of
         true -> couch_util:shutdown_sync(State#st.pid);
         _ -> ok
     end,
-    Pid = spawn_link(?MODULE, update, [Idx, State#st.mod, IdxState]),
-    {reply, ok, State#st{pid=Pid}};
+    % Make sure and flush a possible 'EXIT' message
+    % that's already in our mailbox
+    receive
+        {'EXIT', Pid, _} -> ok
+    after 0 ->
+        ok
+    end,
+    NewPid = spawn_link(?MODULE, update, [Idx, State#st.mod, IdxState]),
+    {reply, ok, State#st{pid=NewPid}};
 handle_call(is_running, _From, #st{pid=Pid}=State) when is_pid(Pid) ->
     {reply, true, State};
 handle_call(is_running, _From, State) ->

-- 
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.

[couchdb] 01/02: Prevent a terrible race condition

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 764168c5b03f17b7adfa5db9a3b7341b01281f44
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Wed Jul 12 15:50:17 2017 -0500

    Prevent a terrible race condition
    
    Looking into #649 I realized there's a pretty terrible race condition if
    an index is compacted quickly followed by an index update. Since we
    don't check the index updater message it would be possible for us to
    swap out a compaction change, followed by immediately resetting to the
    new state from the index updater. This would be bad as we'd possibly end
    up with a situation where our long lived index would be operating on a
    file that no longer existed on disk.
---
 src/couch_index/src/couch_index.erl | 49 +++++++++++++++++++++++--------------
 1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/src/couch_index/src/couch_index.erl b/src/couch_index/src/couch_index.erl
index 9da928d..604d503 100644
--- a/src/couch_index/src/couch_index.erl
+++ b/src/couch_index/src/couch_index.erl
@@ -230,24 +230,37 @@ handle_cast({new_state, NewIdxState}, State) ->
         mod=Mod,
         idx_state=OldIdxState
     } = State,
-    assert_signature_match(Mod, OldIdxState, NewIdxState),
-    CurrSeq = Mod:get(update_seq, NewIdxState),
-    Args = [
-        Mod:get(db_name, NewIdxState),
-        Mod:get(idx_name, NewIdxState),
-        CurrSeq
-    ],
-    couch_log:debug("Updated index for db: ~s idx: ~s seq: ~B", Args),
-    Rest = send_replies(State#st.waiters, CurrSeq, NewIdxState),
-    case State#st.committed of
-        true -> erlang:send_after(commit_delay(), self(), commit);
-        false -> ok
-    end,
-    {noreply, State#st{
-        idx_state=NewIdxState,
-        waiters=Rest,
-        committed=false
-    }};
+    OldFd = Mod:get(fd, OldIdxState),
+    NewFd = Mod:get(fd, NewIdxState),
+    case NewFd == OldFd of
+        true ->
+            assert_signature_match(Mod, OldIdxState, NewIdxState),
+            CurrSeq = Mod:get(update_seq, NewIdxState),
+            Args = [
+                Mod:get(db_name, NewIdxState),
+                Mod:get(idx_name, NewIdxState),
+                CurrSeq
+            ],
+            couch_log:debug("Updated index for db: ~s idx: ~s seq: ~B", Args),
+            Rest = send_replies(State#st.waiters, CurrSeq, NewIdxState),
+            case State#st.committed of
+                true -> erlang:send_after(commit_delay(), self(), commit);
+                false -> ok
+            end,
+            {noreply, State#st{
+                idx_state=NewIdxState,
+                waiters=Rest,
+                committed=false
+            }};
+        false ->
+            Fmt = "Ignoring update from old indexer for db: ~s idx: ~s",
+            Args = [
+                Mod:get(db_name, NewIdxState),
+                Mod:get(idx_name, NewIdxState)
+            ],
+            couch_log:warning(Fmt, Args),
+            {noreply, State}
+    end;
 handle_cast({update_error, Error}, State) ->
     send_all(State#st.waiters, Error),
     {noreply, State#st{waiters=[]}};

-- 
To stop receiving notification emails like this one, please contact
"commits@couchdb.apache.org" <co...@couchdb.apache.org>.