I'm not sure that it is expected since Popen.send_signal does contain the following check:
```
def send_signal(self, sig):
"""Send a signal to the process."""
# Skip signalling a process that we know has already died.
if self.returncode is None:
os.kill(self.pid, sig)
```
Additionally, the following program does not raise a ProcessLookupError despite the program already having exited:
```
import subprocess
import time
proc = subprocess.Popen(["sh", "-c", "exit 0"])
time.sleep(5)
proc.terminate()
```