Blocking/1 was added in quickcheck 1.27 and allows the test to indicate which states might block execution and lets quickcheck find bugs around them. The bug uncovered has to do with when a process holding a worker exits, the DOWN monitor fires and poolboy calls supervisor:terminate_child on the worker the process held. When the EXIT message comes in for that process, we then change the state around such that there is an additional worker. This caused a race condition if there were already checkout messages waiting in the mailbox, because the EXIT message would come in behind the checkout messages, and so even though we had just killed a worker, we'd fail checkouts because we hadn't processed the EXIT yet. The fix is to call into handle_worker_exit right after we terminate the worker, thus updating our state to reflect the actual worker count before processing any messages in the mailbox.
starting process. This is useful for use in e.g. init_per_suite/1 in Common Tests.
Additionally, fix some minor issues in the quickcheck test
- Change a `queue:len/1` call during a checkout in the ready state to use `queue:is_empty/1`. All operations in poolboy that aren't informational or disaster recovery should now theoretically be O(1). - There is now "transaction" support using `transaction/2`. This will run a user defined function passed the worker checked out in a try block, ensuring that the worker is checked back into the pool should the operation fail. - A `child_spec/2` helper for embedding poolboy pools within your supervisors. - Documentation updates.
…, allowing it to terminate
- Monitors are now stored in an ETS table. Simple profiling revealed that a lot of time was being taken in `lists:keytake/3` looking up the refs by pid. This should provide O(1) constant time lookup. - Workers are now no longer required to handle `stop` messages. Workers are terminated using `supervisor:terminate_child/2` and the shutdown strategy is no longer brutal_kill. - Other various cleanups.