Description
If Open4::background fails to spawn a thread then calling #pid on the returned Thread object results in a deadlock. For example, if the command executable does not exist and an Errno::ENOENT exception is raised:
require 'open4'
> true
thread = Open4.background "non-existent-cmd"
> #<Thread:0x252fb70 run>
thread.pid
> fatal: deadlock detected
In this, and any similar cases, Open4 could define a sentinel pid value that Thread#pid would return rather than blocking indefinitely. The current implementation of #pid means this could not be nil as this would result in multiple calls to Queue#pop if Thread#pid is called more than once.
While the user can check whether the thread is alive (via Thread#alive?) a race condition exists between performing this check and calling Thread#pid.
A user can't reliably work around this by calling Thread#pid within a Timeout::timeout block as this also results in a deadlock on some platforms.