In cases where multiple Generator instances might be created, a gc cycle collection run can trigger at any time, potentially removing "old" Generator instances, which then calls __destruct and thus seed, which reset the global mt_rand seed, impacting everyone else.
If another, still live instance of Generator gets used after that, its output is no longer deterministic, since a new random seed was set.
I added a new static class property to Faker\Generator which counts the number of currently existing Generator instances: It gets incremented in construct, and decremented in destruct. Only if this counter reaches 0 does __destruct also call seed to restore the system to a "properly random" state.
Using a global counter is, imho, quite ugly, but since Generator::seed already modifies global state anyway I think its like fighting fire with fire.
Other than that, I think its a quite minimal change that does not impact any other use of Faker. Cases that "properly" only ever use exactly one instance of the Generator will not see any difference in behaviour.
It's not a perfect solution by any means. But I think it is a reasonable one.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 1 week if no further activity occurs. Thank you for your contributions.
What is the reason for this PR?
In cases where multiple Generator instances might be created, a gc cycle collection run can trigger at any time, potentially removing "old" Generator instances, which then calls __destruct and thus seed, which reset the global mt_rand seed, impacting everyone else.
If another, still live instance of Generator gets used after that, its output is no longer deterministic, since a new random seed was set.
Author's checklist
Summary of changes
I added a new static class property to
Faker\Generator
which counts the number of currently existing Generator instances: It gets incremented in construct, and decremented in destruct. Only if this counter reaches 0 does __destruct also callseed
to restore the system to a "properly random" state.Using a global counter is, imho, quite ugly, but since
Generator::seed
already modifies global state anyway I think its like fighting fire with fire. Other than that, I think its a quite minimal change that does not impact any other use of Faker. Cases that "properly" only ever use exactly one instance of the Generator will not see any difference in behaviour.It's not a perfect solution by any means. But I think it is a reasonable one.
Review checklist
CHANGELOG.md