The crash is funny. I don't know how another process could register the name before the reverse mapping of (presumably) a waiter is removed. Perhaps some earlier bug caused lingering garbage in the table? Anyway, I have added a clause to handle the event, so it shouldn't crash anymore.
If we get a value before timeout happens, the timer is still there and will fire at a later time. This means that the timeout will leak from gproc into the process which called await/2 and that process might not be ready to handle the problem. This fix cancels the timer if the normal message is received. It does not eliminate the leak though, since the timer might have fired just before we get to receive the message and thus be in the msg queue of the process. The cancel will then fail and the timeout will have leaked. To give a receiver a hint, we have opted to make timeout into gproc_timeout as an atom() in the hope this will suggest where to look.