Is `Process.send_after(pid, msg, time, opts \\ [])` garbage collected when pid shuts down?

I am using Process.send_after(self(),:wakeup, 100_000) to trigger a GenServer handle_info callback and I am wondering what happens when I have many such GenServer processes come and go. Will the scheduled send_after eat up memory before they are triggered and send to a nonexisting process? Or are they garbage-collected when the process with destination process ID shuts down?

I use process id (not named processes) in the send_after command.

My question is basically if I can be lazy and forget scheduled send_after on GenServer shutdown or if I should honor the returned timer reference and do cancel_timer on GenServer shutdown.

In general all resources of a process are expected to be cleaned up when the process terminates and timers are no exception. So it is safe to be lazy.

2 Likes

I would always capture the return value of Process.send_after and use cancel_timer on it after a certain deadline but that’s mostly a matter of principle. Erlang’s VM is doing just fine in such scenarios and won’t buckle unless you bombard it with a few million of those (and even then it’s questionable if it’s going to buckle).

Also :erts_debug.size(timer) gives us 3 machine words so no need to worry about memory overhead either.

2 Likes

Thank you very much. So to clarify: send_after distinguishes intelligently between process ids (in which case you say timers scheduled to send to send to that process id are cancelled automatically in case that process shuts down before the timer triggered) and named processes (using an atom instead of a process id as first argument, in which case send_after will not clean up the timer before it triggers and the process registred with that atom name at trigger time will receive the message).
Is this correct?

yes it is

2 Likes