我正在尝试写一个shell。当前台进程运行时,分叉的进程管道会被赋予其自己的进程组 ID。然后将终端交给这个进程组 id(使用 tcsetpgrp),shell 等待它终止,然后再给自己终端控制权。这工作得很好。
出现的问题是当我尝试运行后台进程时。同样,我给管道中的所有进程一个进程组 ID,但这次我不给这个组终端控制。运行时,给定后台命令的输出将输出到终端(在执行完成之前),终端同时向用户返回提示。应该发生的是,尝试写入终端的子进程应该得到一个 SIGTTOU 并且它应该停止,但这显然不会发生。我验证了分叉的进程都具有相同的进程组 id,并且这个 id 与 shell 的不同。
在退出 shell(通过 ctrl-c)并返回到运行它的标准 bash shell 后,因为我没有在 shell 终止时获得后台进程,所以后台进程继续运行(除外)。奇怪的是,即使它不是前台进程,这个进程也会继续将输出写入 bash shell。这使我得出结论,要么此后台进程由于 POSIX 错误(不太可能)而没有获得任何 SIGTTOU,它正在处理它们(导致忽略停止的默认操作),或者后台进程正在忽略 SIGTTOU。
有没有办法在执行分叉进程之前确保它在收到 SIGTTOU 时停止(假设 exec 二进制文件没有改变任何东西)?