internal/wayland: increase error detail
All checks were successful
Test / Create distribution (push) Successful in 35s
Test / Sandbox (push) Successful in 2m14s
Test / Hakurei (push) Successful in 3m16s
Test / Hpkg (push) Successful in 4m5s
Test / Sandbox (race detector) (push) Successful in 4m18s
Test / Hakurei (race detector) (push) Successful in 5m8s
Test / Flake checks (push) Successful in 1m21s

This includes targeted paths in the returned errors.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
Ophestra 2025-11-16 02:09:50 +09:00
parent 00771efeb4
commit 3c204b9b40
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q
4 changed files with 46 additions and 24 deletions

View File

@ -36,18 +36,18 @@ func (sc *SecurityContext) Close() error {
func New(displayPath, bindPath *check.Absolute, appID, instanceID string) (*SecurityContext, error) { func New(displayPath, bindPath *check.Absolute, appID, instanceID string) (*SecurityContext, error) {
// ensure bindPath is available // ensure bindPath is available
if f, err := os.Create(bindPath.String()); err != nil { if f, err := os.Create(bindPath.String()); err != nil {
return nil, &Error{Cause: RHostCreate, Errno: err} return nil, &Error{RCreate, bindPath.String(), displayPath.String(), err}
} else if err = f.Close(); err != nil { } else if err = f.Close(); err != nil {
return nil, &Error{Cause: RHostCreate, Errno: err} return nil, &Error{RCreate, bindPath.String(), displayPath.String(), err}
} else if err = os.Remove(bindPath.String()); err != nil { } else if err = os.Remove(bindPath.String()); err != nil {
return nil, &Error{Cause: RHostCreate, Errno: err} return nil, &Error{RCreate, bindPath.String(), displayPath.String(), err}
} }
if fd, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0); err != nil { if fd, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0); err != nil {
return nil, &Error{RHostSocket, err} return nil, &Error{RHostSocket, bindPath.String(), displayPath.String(), err}
} else if err = syscall.Connect(fd, &syscall.SockaddrUnix{Name: displayPath.String()}); err != nil { } else if err = syscall.Connect(fd, &syscall.SockaddrUnix{Name: displayPath.String()}); err != nil {
_ = syscall.Close(fd) _ = syscall.Close(fd)
return nil, &Error{RHostConnect, err} return nil, &Error{RHostConnect, bindPath.String(), displayPath.String(), err}
} else { } else {
closeFds, bindErr := securityContextBindPipe(fd, bindPath, appID, instanceID) closeFds, bindErr := securityContextBindPipe(fd, bindPath, appID, instanceID)
if bindErr != nil { if bindErr != nil {

View File

@ -16,7 +16,7 @@ typedef enum {
HAKUREI_WAYLAND_LISTEN, HAKUREI_WAYLAND_LISTEN,
/* ensure pathname failed, implemented in conn.go */ /* ensure pathname failed, implemented in conn.go */
HAKUREI_WAYLAND_HOST_CREAT, HAKUREI_WAYLAND_CREAT,
/* socket for host server failed, implemented in conn.go */ /* socket for host server failed, implemented in conn.go */
HAKUREI_WAYLAND_HOST_SOCKET, HAKUREI_WAYLAND_HOST_SOCKET,
/* connect for host server failed, implemented in conn.go */ /* connect for host server failed, implemented in conn.go */

View File

@ -38,6 +38,10 @@ type (
Error struct { Error struct {
// Where the failure occurred. // Where the failure occurred.
Cause Res Cause Res
// Attempted pathname socket.
Path string
// Pathname socket to host server. Omitted for libwayland errors.
Host string
// Global errno value set during the fault. // Global errno value set during the fault.
Errno error Errno error
} }
@ -69,8 +73,8 @@ const (
// RListen is returned if listen failed. The global errno is set. // RListen is returned if listen failed. The global errno is set.
RListen Res = C.HAKUREI_WAYLAND_LISTEN RListen Res = C.HAKUREI_WAYLAND_LISTEN
// RHostCreate is returned if ensuring pathname availability failed. Returned by [New]. // RCreate is returned if ensuring pathname availability failed. Returned by [New].
RHostCreate Res = C.HAKUREI_WAYLAND_HOST_CREAT RCreate Res = C.HAKUREI_WAYLAND_CREAT
// RHostSocket is returned if socket failed for host server. Returned by [New]. // RHostSocket is returned if socket failed for host server. Returned by [New].
RHostSocket Res = C.HAKUREI_WAYLAND_HOST_SOCKET RHostSocket Res = C.HAKUREI_WAYLAND_HOST_SOCKET
// RHostConnect is returned if connect failed for host server. Returned by [New]. // RHostConnect is returned if connect failed for host server. Returned by [New].
@ -96,21 +100,25 @@ func (e *Error) Error() string {
case RNotAvail: case RNotAvail:
return "compositor does not implement security_context_v1" return "compositor does not implement security_context_v1"
case RSocket, RBind, RListen: case RSocket:
if e.Errno == nil { if e.Errno == nil {
return "socket operation failed" return "socket operation failed"
} }
return e.Errno.Error() return "socket: " + e.Errno.Error()
case RBind:
return e.withPrefix("cannot bind " + e.Path)
case RListen:
return e.withPrefix("cannot listen on " + e.Path)
case RHostCreate: case RCreate:
if e.Errno == nil { if e.Errno == nil {
return "cannot ensure wayland pathname socket" return "cannot ensure wayland pathname socket"
} }
return e.Errno.Error() return e.Errno.Error()
case RHostSocket: case RHostSocket:
return e.withPrefix("socket for host wayland server") return e.withPrefix("socket")
case RHostConnect: case RHostConnect:
return e.withPrefix("connect to host wayland server") return e.withPrefix("cannot connect to " + e.Host)
default: default:
return e.withPrefix("impossible outcome") /* not reached */ return e.withPrefix("impossible outcome") /* not reached */
@ -142,6 +150,7 @@ func securityContextBind(
if e.Cause == RSuccess { if e.Cause == RSuccess {
return nil return nil
} }
e.Path = socketPath
return &e return &e
} }

View File

@ -53,30 +53,43 @@ func TestError(t *testing.T) {
{"socket", wayland.Error{ {"socket", wayland.Error{
Cause: wayland.RSocket, Cause: wayland.RSocket,
Errno: stub.UniqueError(4), Errno: stub.UniqueError(4),
}, "unique error 4 injected by the test suite"}, }, "socket: unique error 4 injected by the test suite"},
{"bind", wayland.Error{
Cause: wayland.RBind,
Path: "/hakurei.0/18783d07791f2460dbbcffb76c24c9e6/wayland",
Errno: stub.UniqueError(5),
}, "cannot bind /hakurei.0/18783d07791f2460dbbcffb76c24c9e6/wayland: unique error 5 injected by the test suite"},
{"listen", wayland.Error{
Cause: wayland.RListen,
Path: "/hakurei.0/18783d07791f2460dbbcffb76c24c9e6/wayland",
Errno: stub.UniqueError(6),
}, "cannot listen on /hakurei.0/18783d07791f2460dbbcffb76c24c9e6/wayland: unique error 6 injected by the test suite"},
{"socket invalid", wayland.Error{ {"socket invalid", wayland.Error{
Cause: wayland.RSocket, Cause: wayland.RSocket,
}, "socket operation failed"}, }, "socket operation failed"},
{"host create", wayland.Error{ {"create", wayland.Error{
Cause: wayland.RHostCreate, Cause: wayland.RCreate,
}, "cannot ensure wayland pathname socket"}, }, "cannot ensure wayland pathname socket"},
{"host create path", wayland.Error{ {"create path", wayland.Error{
Cause: wayland.RHostCreate, Cause: wayland.RCreate,
Errno: &os.PathError{Op: "create", Path: "/proc/nonexistent", Err: syscall.EEXIST}, Errno: &os.PathError{Op: "create", Path: "/proc/nonexistent", Err: syscall.EEXIST},
}, "create /proc/nonexistent: file exists"}, }, "create /proc/nonexistent: file exists"},
{"host socket", wayland.Error{ {"host socket", wayland.Error{
Cause: wayland.RHostSocket, Cause: wayland.RHostSocket,
Errno: stub.UniqueError(5), Errno: stub.UniqueError(7),
}, "socket for host wayland server: unique error 5 injected by the test suite"}, }, "socket: unique error 7 injected by the test suite"},
{"host connect", wayland.Error{ {"host connect", wayland.Error{
Cause: wayland.RHostConnect, Cause: wayland.RHostConnect,
Errno: stub.UniqueError(6), Host: "/run/user/1971/wayland-1",
}, "connect to host wayland server: unique error 6 injected by the test suite"}, Errno: stub.UniqueError(8),
}, "cannot connect to /run/user/1971/wayland-1: unique error 8 injected by the test suite"},
{"invalid", wayland.Error{ {"invalid", wayland.Error{
Cause: 0xbad, Cause: 0xbad,
@ -84,8 +97,8 @@ func TestError(t *testing.T) {
{"invalid errno", wayland.Error{ {"invalid errno", wayland.Error{
Cause: 0xbad, Cause: 0xbad,
Errno: stub.UniqueError(5), Errno: stub.UniqueError(9),
}, "impossible outcome: unique error 5 injected by the test suite"}, }, "impossible outcome: unique error 9 injected by the test suite"},
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {