Browse Source

Merge pull request #168 from uwiger/uw-pool-bad-size-adjustment

Uw pool bad size adjustment
Ulf Wiger 6 years ago
parent
commit
4c733677eb
2 changed files with 33 additions and 2 deletions
  1. 7 2
      src/gproc_pool.erl
  2. 26 0
      test/gproc_tests.erl

+ 7 - 2
src/gproc_pool.erl

@@ -833,8 +833,13 @@ do_remove_worker_(Pool, Name) ->
     case (NewLen = length(Ws1)) - length(Ws0) of
         0 -> ok;
         Diff when Diff < 0 ->
-            {_, Type} = gproc:get_value(K, shared),
-            gproc:set_value_shared(K, {NewLen, Type})
+            case gproc:get_attribute(K, shared, auto_size) of
+                true ->
+                    {_, Type} = gproc:get_value(K, shared),
+                    gproc:set_value_shared(K, {NewLen, Type});
+                false ->
+                    ok
+            end
     end,
     gproc:set_attributes_shared(K, [{workers, Ws1}]),
     ok.

+ 26 - 0
test/gproc_tests.erl

@@ -162,6 +162,8 @@ reg_test_() ->
       , ?_test(t_is_clean())
       , {spawn, ?_test(?debugVal(t_simple_pool()))}
       , ?_test(t_is_clean())
+      , {spawn, ?_test(?debugVal(t_pool_add_worker_race()))}
+      , ?_test(t_is_clean())
      ]}.
 
 t_simple_reg() ->
@@ -1003,6 +1005,30 @@ t_simple_pool()->
     %% should be able to delete the pool now
     ?assertEqual( gproc_pool:delete(p1), ok).
 
+%% verifying #167 - Removing a worker from a pool does not make room
+%% for a new worker (size was erroneously adjusted down, though auto_size = false)
+t_pool_add_worker_race() ->
+    ok = gproc_pool:new(p2, direct, [{size, 1}, {auto_size, false}]),
+    [] = gproc_pool:defined_workers(p2),
+    Pos1 = gproc_pool:add_worker(p2, worker1),
+    [{worker1, Pos1, 0}] = gproc_pool:defined_workers(p2),
+    io:fwrite("G = ~p~n", [ets:tab2list(gproc)]),
+    Pid = spawn(fun() ->
+                        true = gproc_pool:connect_worker(p2, worker1),
+                        receive after 100 -> bye end
+                end),
+    Monitor = monitor(process, Pid),
+    receive
+        {'DOWN', Monitor, process, _, _} -> ok
+    end,
+    true = gproc_pool:remove_worker(p2, worker1),
+    [] = gproc_pool:defined_workers(p2), %% the pool seems to be empty
+    Pos2 = gproc_pool:add_worker(p2, worker2), %% throws error:pool_full
+    true = is_integer(Pos2),
+    true = gproc_pool:force_delete(p2).
+
+
+
 get_msg() ->
     receive M ->
 	    M