Skip to content

Conversation

alexrp
Copy link
Member

@alexrp alexrp commented Oct 9, 2025

Codeberg: https://codeberg.org/ziglang/zig/pulls/3

#25227 laid the groundwork for me to finally do some porting and other improvements in std.debug that I'd been meaning to do for ages. Thanks @mlugg!

Greatly expanded target support for segfault handling/unwinding

This PR combined with

results in us having greatly expanded target coverage for segfault handling and stack traces in general. There's still #25422 which I plan to tackle after this, but on basically every other target that sees real use with Zig (and probably even a few that don't), we now have working stack traces on crashes and when using DebugAllocator.

I made a couple of decisions for this based on the fact that we don't expose the signal_ucontext_t type outside of std.debug.cpu_context:

  • Adding all the floating point and vector state to every ucontext_t and mcontext_t variant was way, way too much work, especially when we don't even use the stuff. So I deleted all that and kept only the bare minimum needed to reach into general-purpose registers.
  • There is no particularly compelling reason to stick to the naming and struct nesting used in the system headers. So we can actually unify the access patterns for almost all of these variants by taking some liberties here; as a result, fromPosixSignalContext() is now much nicer to read and extend.

Removal of ucontext_t and related types/functions

This type is useful for two things:

  • Doing non-local control flow with ucontext.h functions.
  • Inspecting machine state in a signal handler.

The first use case is not one we support; we no longer expose bindings to those functions in the standard library. They're also deprecated in POSIX and, as a result, not available in musl.

The second use case is valid, but is very poorly served by the standard library. As evidenced by my changes to std.debug.cpu_context.signal_context_t, users will be better served rolling their own ucontext_t and especially mcontext_t types which fit their specific situation. Further, these types tend to evolve frequently as architectures evolve, and the standard library has not done a good job keeping up, or even providing them for all supported targets.

@alexrp alexrp added breaking Implementing this issue could cause existing code to no longer compile or have different behavior. release notes This PR should be mentioned in the release notes. labels Oct 9, 2025
@alexrp alexrp requested a review from mlugg October 9, 2025 08:18
@alexrp alexrp changed the title Std debug std.debug: greatly expand target support for segfault handling/unwinding, and remove public ucontext_t completely Oct 9, 2025
Copy link
Member

@mlugg mlugg left a comment

Choose a reason for hiding this comment

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

This looks great!

Copy link
Collaborator

@linusg linusg left a comment

Choose a reason for hiding this comment

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

Also LGTM. I really like the addition of more reference links :)

},

.illumos => &.{
.x86,
Copy link
Contributor

Choose a reason for hiding this comment

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

Illumos and Solaris haven't supported x86 for a while now. You can run old binaries but it's discouraged to create new ones.

Copy link
Member Author

Choose a reason for hiding this comment

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

I know Solaris hasn't, but illumos seems to still support userspace 32-bit applications? http://www.tribblix.org/32bit.html

Copy link
Contributor

Choose a reason for hiding this comment

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

It only matters how you define can_unwind:

  1. Does this arch-os-abi combo support unwinding?
  2. Does the Zig compiler emit code for this combo?

If 2 doesn't matter then you may as well add x86 to Solaris as well. It seems like it doesn't since sparc64-solaris isn't there.

Copy link
Member Author

Choose a reason for hiding this comment

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

sparc64-solaris is just a to-do along with sparc64-linux and others; I'll do a later pull request that adds full SPARC unwinding to all of std.debug (unless @mlugg beats me to it?).

In general, I'm going off test/llvm_targets.zig for what targets are relevant here. That file in turn boils down to which targets are still supported by the developers/vendor of the OS. If a target is missing here, it's probably because it's missing in test/llvm_targets.zig, while a @compileError represents work to be done.

That said, I'm not sure I entirely understand point 2; the Zig compiler should in theory be able to emit code for x86-solaris, sparc-solaris, sparc64-solaris, etc. It's just that if a target is effectively dead and no one cares about it, we're not going to bother maintaining code paths for it.

I made a couple of decisions for this based on the fact that we don't expose the
signal_ucontext_t type outside of the file:

* Adding all the floating point and vector state to every ucontext_t and
  mcontext_t variant was way, way too much work, especially when we don't even
  use the stuff. So I deleted all that and kept only the bare minimum needed to
  reach into general-purpose registers.
* There is no particularly compelling reason to stick to the naming and struct
  nesting used in the system headers. So we can actually unify the access
  patterns for almost all of these variants by taking some liberties here; as a
  result, fromPosixSignalContext() is now much nicer to read and extend.
This type is useful for two things:

* Doing non-local control flow with ucontext.h functions.
* Inspecting machine state in a signal handler.

The first use case is not one we support; we no longer expose bindings to those
functions in the standard library. They're also deprecated in POSIX and, as a
result, not available in musl.

The second use case is valid, but is very poorly served by the standard library.
As evidenced by my changes to std.debug.cpu_context.signal_context_t, users will
be better served rolling their own ucontext_t and especially mcontext_t types
which fit their specific situation. Further, these types tend to evolve
frequently as architectures evolve, and the standard library has not done a good
job keeping up, or even providing them for all supported targets.
@alexrp
Copy link
Member Author

alexrp commented Oct 10, 2025

Added some missing align(8) and align(16) to a few of the mcontext_ts since we're omitting the later field declarations that would normally cause them to gain that higher type alignment. Something to keep in mind for future work in this file.

@alexrp alexrp enabled auto-merge October 10, 2025 02:46
@alexrp alexrp merged commit f010a31 into ziglang:master Oct 10, 2025
9 checks passed
@alexrp alexrp deleted the std-debug branch October 10, 2025 12:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Implementing this issue could cause existing code to no longer compile or have different behavior. release notes This PR should be mentioned in the release notes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants