Skip to content

libct/utils: drop go:linkname from UnsafeCloseFrom#5252

Open
kolyshkin wants to merge 1 commit intoopencontainers:mainfrom
kolyshkin:hall-of-shame
Open

libct/utils: drop go:linkname from UnsafeCloseFrom#5252
kolyshkin wants to merge 1 commit intoopencontainers:mainfrom
kolyshkin:hall-of-shame

Conversation

@kolyshkin
Copy link
Copy Markdown
Contributor

This stems from the discussion at go.dev/issue/67639, which proposed adding a public API to query if an FD is internal to Go. It was rejected and the proposal is to not close epoll FDs instead.

Let's do just that.

As a result, we can drop the last use of go:linkname and thus runc can be removed from the Go hall of shame (see go.dev/issue/67401 and golang/go@5fc5555feb0).

@kolyshkin
Copy link
Copy Markdown
Contributor Author

I'm not quite sure whether this is 1.5 or 1.6 material. On one hand, the change is small and focused and including it into 1.5 will save us half a year. OTOH it could cause some kind of breakage.

I am also not very happy about the overhead.

@kolyshkin kolyshkin marked this pull request as ready for review April 17, 2026 00:24
@kolyshkin kolyshkin requested review from cyphar and lifubang April 17, 2026 00:24
func runtime_IsPollDescriptor(fd uintptr) bool //nolint:revive
func isEpollFd(fd int) bool {
target, err := os.Readlink("/proc/self/fd/" + strconv.Itoa(fd))
return err == nil && strings.HasPrefix(target, "anon_inode:[event")
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: err check can be dropped entirely

@cyphar
Copy link
Copy Markdown
Member

cyphar commented Apr 17, 2026

Honestly I don't really mind being in the Go "hall of shame" for this, FWIW.

Yes, epoll fds are not something you can exploit to keep with execve as far as we know but I really don't like these kinds of half-measures when we have a solution that actually works (and is less expensive!). :/

This stems from the discussion at go.dev/issue/67639, which proposed
adding a public API to query if an FD is internal to Go. It was rejected
and the proposal is to not close epoll FDs instead.

Let's do just that.

As a result, we can drop the last use of go:linkname and thus runc can
be removed from the Go hall of shame (see go.dev/issue/67401 and
golang/go@5fc5555feb0).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
@lifubang
Copy link
Copy Markdown
Member

lifubang commented Apr 19, 2026

Quite agree with cyphar.

The go:linkname approach provides a precise, zero-cost check directly from the runtime. While I understand the concern about using internal runtime functions, in this case, I think the trade-off favors correctness and performance(as mentioned in #5252 (comment)), and I appreciate the effort to clean up the codebase.

If we want a clean long-term solution, the right path is to continue pushing Go upstream to expose a public API (like runtime.IsInternalDescriptor), as originally proposed in golang/go#67639.

Moreover, this is fundamentally a responsibility issue: these fds are opened by the Go runtime itself, not by user code. The runtime knows exactly which fds it owns -- we don't. It is therefore the runtime's responsibility to expose a public API so that callers can identify and skip those fds (as proposed in golang/go#67639).

Asking runc to guess which fds the runtime is using -- via heuristics over /proc -- may inadvertently invert the ownership model, rather than address the root cause.

@kolyshkin
Copy link
Copy Markdown
Contributor Author

Honestly I don't really mind being in the Go "hall of shame" for this, FWIW.

Yes, epoll fds are not something you can exploit to keep with execve as far as we know but I really don't like these kinds of half-measures when we have a solution that actually works (and is less expensive!). :/

I agree (and this is why I opened golang/go#67639 in the first place, but Go upstream essentially says "go check fd type before closing it".

One other alternative would be to stop go runtime entirely (we're about to exec and don't need any of it). This was suggested here and I guess I can try to propose it.

@kolyshkin
Copy link
Copy Markdown
Contributor Author

One other alternative would be to stop go runtime entirely (we're about to exec and don't need any of it). This was suggested here and I guess I can try to propose it.

Alas this won't work; in case we've closed the netpoll fds, we can "stop the world" (including sysmon which calls netpoll) but we can not "restart" it -- in case execve fails. Since netpoll fds are closed already, it will panic upon restart. So this would be a one-way operation.

Not that we can do much in case execve fails; but I doubt this proposal will be accepted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants