SysProcAttr.Noctty
通过在执行前调用 RawSyscall(SYS_IOCTL, 0, uintptr(TIOCNOTTY), 0)
来实现。TIOCNOTTY
ioctl 仅在控制终端的文件描述符上实现,这并不一定与子进程的 FD 0 相连。这意味着 SysProcAttr.Noctty
仅在 cmd.Stdin
是会话终端时有效,而且不可能同时运行一个既没有终端又具有功能性 stdin 的子进程。
这个问题出现是因为我正在为一个使用 /dev/tty
与用户交互并分别获取输入的应用程序编写测试。我想测试当 /dev/tty
不可用时会发生什么,所以我用 SysProcAttr.Noctty
启动子进程,并为其提供一个 stdin 管道。结果是在管道上发出了 TIOCNOTTY
,导致 operation not supported by device
。
下面是一个简短的例子:
package main
import (
"os"
"os/exec"
"syscall"
)
func main() {
if len(os.Args) > 1 && os.Args[1] == "child" {
_, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
if err != nil {
println(err.Error()) // expect: "device not configured"
}
return
}
cmd := exec.Command(os.Args[0], "child")
// Uncomment this block to have Noccty work correctly,
// but making stdin in the child unusable.
// f, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
// if err != nil {
// panic(err)
// }
// cmd.Stdin = f
cmd.Stderr = os.Stderr // to see the output
cmd.SysProcAttr = &syscall.SysProcAttr{}
cmd.SysProcAttr.Noctty = true
if err := cmd.Run(); err != nil {
panic(err)
}
}
5条答案
按热度按时间zfciruhq1#
另外,由于
Setctty
在Noctty
之后应用,我们也无法测试stdin是一个终端但没有控制终端的情况(如果操作顺序颠倒,这种情况是可能的)。dzhpxtsq2#
Well,
Noctty
正在按照文档进行操作。对于这里需要添加的内容有什么建议吗?i7uaboj43#
对我来说,最直接的解决方案似乎是在
/dev/tty
上打开并发行TIOCNOTTY
,但也许我没有看到一些理由认为它会是不理想的。如果出于某种原因/dev/tty
不可用,它仍然可以尝试 FD 0 作为后备。任何当前工作的应用的行为都不会改变。vu8f3i0k4#
听起来有道理。看看是否会出现任何问题会很有趣。
wa7juj8i5#
有人打算提出更详细的修复方案(例如一个CL)吗?还是我应该去别的地方找人来处理?(我标记它需要决策,因为我认为测试修复基本上给了我们决策。还有可能是里程碑1.20吗?)