Detect pid reuse

Jan Chochol jan.chochol@REDACTED
Fri Jul 10 07:31:52 CEST 2020


> This solution assumes the new process that is reusing the pid will also be a connection process that understands this protocol.

Thanks for pointing out the error in my algorithm.

What about a completely different approach - instead of pushing
messages to connection processes, they will instead pull messages.

You will need to introduce some proxy message queue (with stable PID!)
for a given database.
When you want to call DB operation, you will instead add a request to
the proxy message queue (with some references to requests, and PID of
the calling process - something like "gen:call").
The connection process will then poll on the proxy message queue for
their database. Once it receives a request, it will send a response to
the queue (to confirm processing), and the queue will respond to the
original caller.

Problem is, that it will be slower (more messages), queue will need to
monitor connection process during execution (there should not be
problem with PID reuse, as poll request will be synchronous, and there
will be no time for the connection process to die before monitoring,
as it will be waiting for poll response), but it should solve the
problem.

Regards,
Jan

On Thu, Jul 9, 2020 at 10:12 PM Dániel Szoboszlay <dszoboszlay@REDACTED> wrote:
>>
>> Back to your problem - PID reuse is painful to workaround. I would
>> suggest something like storing in a process belonging to connection,
>> which database they are connected to (some kind of validation data).
>> You will also need to extend "gen_server:call" with the same
>> validation data, and the connection process will then check, if
>> validation data is correct.
>
>
> This solution assumes the new process that is reusing the pid will also be a connection process that understands this protocol. But there's no guarantee for that, once you're fighting pid reuse, the new process may be any process that your system can spawn. It may not even execute a receive ever.
>
> The only safe solution I can think of would go like this:
>
> Find out the pid you should use
> Monitor the pid
> Find out the pid you should use again.
>
> If it's different from the old one you already have, you've just run into pid reuse. Demonitor the old pid and go back to step 2 with the new one.
> If it's the same as the old one, you are most likely having the monitor on the process you want to use. (It's still theoretically possible that in step 1 you got a pid of process X, which died and a completely different process Y reused its pid, so you monitored that in step 2, but process Y also died and now a new process Z is reusing the pid, and Z is actually the replacement of the dead process X, so in step 3 you actually look up Z. But don't worry, you're covered with this algorithm even for this madness!)
>
> Whenever you need to receive a message from the pid, also have a receive clause for the DOWN message from the monitor. This includes receives within the gen_* modules, so either be very disciplined and use your custom reimplementation of gen_server:call/cast/... instead, or build your own patched OTP, yay!
> Be sure that all processes in your system can handle unexpected garbage messages (by at least throwing them away from their mailbox), because they themselves can become pid reusers and receive messages intended to different processes. Also make sure that all processes are capable of telling messages targeted to them from messages intended to different processes.
>
> However, I'm afraid this would be an extremely inefficient solution with the double pid lookups and monitors alone. And steps 4 & 5 seem practically impossible to implement correctly.
>
> Cheers,
> Daniel


More information about the erlang-questions mailing list