go x/sys/unix: IoctlGetPtmget在NetBSD上获取ptsname失败

svgewumm  于 4个月前  发布在  Go
关注(0)|答案(6)|浏览(42)

Go版本
go版本 go1.21.8 netbsd/amd64

go env 在你的模块/工作区中的输出:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/root/.cache/go-build'
GOENV='/root/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='netbsd'
GOINSECURE=''
GOMODCACHE='/root/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='netbsd'
GOPATH='/root/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/pkg/go121'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/pkg/go121/pkg/tool/netbsd_amd64'
GOVCS=''
GOVERSION='go1.21.8'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1420044071=/tmp/go-build -gno-record-gcc-switches'

你做了什么?

尽管测试用例 TestIoctlPtmget 在NetBSD上通过,但调试发现 ptm.Sn 是一个填充了零的字节数组,从而阻止我们获得 ptsname 。日志始终显示 sfd = 0, ptsname = ,而在正常情况下,我们期望看到类似 sfd = 0, ptsname = /dev/pts/0 的内容。
以下是 amd64 架构相关代码的示例。

func TestIoctlPtmget(t *testing.T) {
	fd, err := unix.Open("/dev/ptmx", unix.O_NOCTTY|unix.O_RDWR, 0666)
	if err != nil {
		t.Skip("failed to open /dev/ptmx, skipping test")
	}
	defer unix.Close(fd)

	ptm, err := unix.IoctlGetPtmget(fd, unix.TIOCPTSNAME)
	if err != nil {
		t.Fatalf("IoctlGetPtmget: %v\n", err)
	}

	t.Logf("sfd = %v, ptsname = %v", ptm.Sfd, unix.ByteSliceToString(ptm.Sn[:]))
}

const TIOCPTSNAME = 0x40287448

type Ptmget struct {
	Cfd int32
	Sfd int32
	Cn  [1024]byte
	Sn  [1024]byte
}

根据我的调查,这个错误是由于 Ptmget 结构中 CnSn 的长度与 TIOCPTSNAME 的值不匹配所引起的。
NetBSD: src/sys/sys/ttycom.h 中,我们可以发现 TIOCPTSNAME 的值与 Ptmget 的大小有关。

#include <iostream>

#define	IOCPARM_MASK	0x1fff		/* parameter length, at most 13 bits */
#define	IOCPARM_SHIFT	16
#define	IOCGROUP_SHIFT	8
#define	_IOC(inout, group, num, len) \
    ((inout) | (((len) & IOCPARM_MASK) << IOCPARM_SHIFT) | \
    ((group) << IOCGROUP_SHIFT) | (num))
#define	IOC_OUT		(unsigned long)0x40000000
#define	_IOR(g,n,t)	_IOC(IOC_OUT,	(g), (n), sizeof(t))
#define TIOCPTSNAME 	 _IOR('t', 72, struct ptmget)	/* ptsname(3) */

#define PATH_MAX 1024

struct ptmget {
	int		cfd;
	int		sfd;
	char	cn[PATH_MAX];
	char	sn[PATH_MAX];
};

int main() {
    std::cout << TIOCPTSNAME;
}

当我们将 PATH_MAX 设置为代码中当前使用的 1024 时,对应的 TIOCPTSNAME 值应该是 0x48087448 ,而不是为 386 / amd64 / arm64 定义的 arm (TIOCPTSNAME 的定义与当前代码中的 0x40287448 匹配正确)。
TIOCPTSNAME 为当前代码中使用的 0x40287448 时,相应的 PATH_MAX 应该为 16。这确实与 netbsd man page / ptm 中的描述相符。
我将很快提交一个 CL 以修复此错误。这是我第一次为 Go 提交 CL。请告诉我是否有任何不适当的地方或有任何反馈。

你看到了什么发生?

没有

你期望看到什么?

没有

eit6fx6z

eit6fx6z1#

https://go.dev/cl/579476提到了这个问题:unix: fix IoctlGetPtmget get empty ptsname on NetBSD.

ffvjumwh

ffvjumwh2#

如果理解了bug报告,那么修复应该调整TIOCPTSNAME的值,而不是改变结构体大小。

3phpmpom

3phpmpom3#

如果我理解了这个bug报告,那么修复方法应该是调整TIOCPTSNAME的值,而不是改变结构体大小。是的,通过将TIOCPTSNAME0x40287448设置为0x48087448,IoctlGetPtmget也可以获得正确的ptsname,而不需要改变Ptmget结构体的大小。请问我需要遵循这个逻辑来修改我提交的代码吗?

tquggr8v

tquggr8v4#

我可以问一下,我需要按照这个逻辑修改我提交的代码吗?
对不起,我不明白你的问题。

7rtdyuoh

7rtdyuoh5#

函数unix.IoctlGetPtmget在Mac OS上不可用吗?我完全看不到这个功能。

tyg4sfes

tyg4sfes6#

函数unix.IoctlGetPtmget在Mac OS上不可用吗?我完全看不到这个功能。
不,如果需要的话,请查看iyzyi/aiopty/pty/nixpty/native/native_darwin.go。

相关问题