State of networking in `std.Io`

Not sure if I understand what you mean.

To fix my problem, I would then add a localAddress option to connect. But that’s only fixing the symptom. The real fix would be to split creating the socket and connecting. But that’s affecting all std.Io implementations structurally. There are a couple more options, all of them breaking changes.

How likely is it that the guy working on std.Io would accept the PR as is or even look at it any time soon?

I don’t think this is the right approach. Something as important as the abstraction over a cross platform abstraction over all OS functionality affected by IO and concurrency should not be driven by fixes of random users hitting a wall.

What should be done here in the concrete case is to not merge multiple API steps into a single operation if the operation only supports a subset of what the OS supports. There was a reason for this decision and likely a good one. They guy who made the decision knows and this guy should drive the design. Whatever I would do ignores the reason for why it was done otherwise.

It’s not that I’m too lazy to contribute, I just don’t believe that this kind of thing is what should be driven by me or people in my situation.

I came across this problem in the past. I don’t remember the details, but it was related to reading file attrs with stat. The std implementation did not deliver the complete set of data from the syscal (or something similar) and as a consequence, I had to revert to direct syscall interface. The reasoning behind it was that std wants to be platform agnostic or work cross platform and thus cannot support all OS fully.

This argument certainly makes sense in the context in which it was made, but the approach of the lowest common denominator is not a universal solution, it’s only convenient. There must be a path to access the guts of a system if the use case needs it. This is always there in the absence of abstractions like std.Io. You can always call out to linux/win/… But with abstractions that maintain their own state and make their own assumptions about it (a socket must be blocking, …) that are not innate to the interface but the implementation, this escape hatch disappears. The error handling is an example for that, where two contracts conflict (linux semantics of non-blocking connect and std.Io abstraction contract).

std.Io must be designed to be convenient (that’s the whole point of it) but it must also be correct and complete. I don’t believe it can be both without a coherent design with these goals in mind. My PR would fix my problem or maybe the issue with socket create/connect but not all the other issues that might be lurking around the corner. But my PR would be breaking code if accepted. And the next PR would too.

I probably sound like the typical whiner who complains and doesn’t want to contribute. What I try to say is that std.Io should not grow organically. And it’s too big to be hacked together in a week or too. It’s also too important to be unfinished, because there is no adopting std.Io a bit and using other things in parallel, because std.Io when adopted becomes the architecture baseline of whatever is using it.

Arguing from my personal perspective, patching up std.Io doesn’t solve my problems, because that only adds one more layer of vendored dependencies and makes it harder for the others I have to stack on top of them, in this concrete example I would change std.Io signatures, then ask zio to use the speculative new structure, then ask httpx to also use it. I don’t think that is productive for me. I could try to become a core member of Zig, and I would love to, but that’s also not solving my concrete problems to bind to a local address or read file attributes, etc.

I believe I understand your perspective and I don’t think mine should override yours, I just want to make sure you see mine too :wink:

14 Likes

Since std.Io is pretty new, breaking changes should be welcomed and expected.

Very!

Au contraire this is exactly how development should move forward. The compiler team is driven primarily by the needs of the compiler, but std, especially std.Io should provide a solid base for all users of Zig.

4 Likes

We disagree here, and that’s fine. I’m speaking for myself only. You? Is your position that of the core team, by association or coincidence? If so, I will take the time and propose changes to std.Io as a PR. I just don’t want to spend a week or two if there is no chance that the results are not just hanging around unseen.

3 Likes

Who would you send a std.Io PR to ?

That’s a reasonable point right there, and I think I agree. A possible counterpoint would be that if you provided a PR that solved just your problem, that would give as much information as possible about both your problem and your solution to the core team. It might be usable as-is, it might not, but it might help inform the discussion. It’s kind of in the spirit of Fred Brooks’s ‘build one to throw away’.

(All moot if the core team has a plan and doesn’t want the feedback, I’m very much generalizing.)

1 Like

I’m sorry, I really don’t want to start an argument, but this is just not true. I started this thread in July. It was after I opened a bunch of std.Io PRs and saw no feedback at all. So I understood that std.Io is not the focus right now, but I asked when it could be.

PRs that are just technical fixes, or do something straightforward, essentially finishing something unfinished, do eventually get merged.

Here are two PRs, that need some API design, both are very important, in my view:

https://codeberg.org/ziglang/zig/pulls/31809 (5 months old)

https://codeberg.org/ziglang/zig/pulls/35325 (4 months old)

Neither of them has feedback from someone with authority on std.Io API design.

18 Likes

Completely agree with your approach. In this particular situation it’s however more complex.

I can send a PR with an interface change, but then I also need to implement all implementations in std.Io AND the implementation I’m using (zio in my case).

Whatever feature I am implementing with that fix would then still need the workaround, because I don’t know if my PR will get accepted and even if so, it will not be available anytime soon.

I’m actually following this PR approach with many zig dependencies and very successful. Most lib authors are super friendly and welcome these PRs, for my latest project I had my patches land in zlua, httpx, and zio in almost no time.

But Zig is an entirely different beast, it’s not a library with a single maintainer who knows exactly what they want in their project. It’s a team effort and its scope is monumental and so are the waiting times to get your fringe use cases served (well mine in this case). It’s really quite comparable to Linux as a project, not in scale, but in nature. Linux however has the infrastructure to process such changes. They have a lot of contributors come and go, often for reasons similar to mine, and a few maintainers who stay and manage the chaos.

But again, I’m happy to contribute if the result can become a contribution and is not doomed to be a waste of time.

3 Likes

I’m going to throw my 2 cents in here.

I do think that the Zig team is stretching themselves at this point too thin. I can feel the want to do many different things. But at this point they put so many different things they want to do (and do at kinda the same time) on their plate, that each individual thing only shows very little progress each release, even if the total progress is actually quite a lot.

And then there’s std.Io.Batch. I like the std.Io.Operation abstraction and also hope that it can long term get a “chain” operation to support io_uring’s chain operation (and emulate it on platforms without such a feature).
But one should think of Batch more like of Windows’ Completion Ports than of Poll, even if that was kinda the original goal. But that’s actually good enough. (No, really, write e.g. a program where you read and write data to a pipe where you are in charge of both ends in raw Windows CP and one with Zig’s Batch and you’ll notice that structurally it’s same.)

About polling:
In general async IO can be divided into polling and completion based IO. Poll is just “Is this ready for this kind of operation?”, which has the downside of not asking for how much you want to do and turns out on Unix-likes this is an incredibly leaky abstraction. Completion is just “Please do this and tell me when you finished”.
Some operating systems only support polling (e.g. OpenBSD), some only completion (e.g. Windows with the exception that Windows Vista added WASPoll for sockets only, not even pipes) and some are a mix (e.g. Linux with (e)poll (even if Linux always says that an fd for a file is readable or writeable, no matter what, including network mounts) and io_uring).
The original idea for Batch was to solve the “poll” use case (which could also have been solved by the Evented implementation), but now it works more completion based, likely because you can’t really implement a polling based API with a completion based one, but you can do so pretty easily the other way around.

Also, while writing this I noticed that you can’t create pipes with std.Io…

On std.Io.Batch, yes, it’s a good abstraction and I want it to be finished. This kind of mini event loop is important in many cases. There are open PRs to add connect and accept there, the connect one probaly needs more work, but the accept one is good to merge. What std.Io.Batch needs is a way to cancel individual operations, there is an open PR for that. And there is currently a bug in std.Io.Batch, where it leaves finished operations inside the pending queue (if I remember correctly), there is also open PR for that.

On polling, all systems can do it. The only problematic one is Windows, but even there, you can emulate it with zero sized reads. Linux/io_uring supports poll just fine. Having poll in the interface allows for much better C integration, so I think it’s worth it, but I agree that it can be considered an abstraction leak.

3 Likes

Reading your post: “could have also been evented”:

That’s another reason why having a single brain behind the design of std.Io would be benefitial. All OS abstractions have amassed technical debt over the decades and on top of that there is the multi-platform issue.

Applications or services end up behaving the same, no matter where they run. So we developers somehow despite all odds manage to find abstractions that work across these chaotic mine fields.

std.Io is conceptually different enough from every other approach I saw, that it can actually find new abstractions that might not only work and work better than what people hack together, it might actually have the potential to just solve this chaos.

But that can’t work if it just grows organically from one day to the next, this needs to be designed. And it can’t be a least common denominator design, because that would always keep it in the realm of playground or theory.

Again, this is not meant as critique, I’m trying to express an observation influenced by my opinions.

uhhh git@codeberg.org:ziglang/zig?


@KilianHanich

I think “stretching themselves too thin” is applying an inappropriately corporate lens. The Zig core team (when I got to hang out with most of them this week) seems happy, fun to hang out with, and thriving.

Of course, the kind of PRs that can be merged when the core team is at a conference is different from when they are not. I don’t know if you work in open source a bunch or not, and I forget if this was originally Richard Hipp or Andrew, but I loved the “no emergencies” perspective they shared. If you stay communicative and friendly instead of crashing out on the forum, things will go better for you. That’s just true in life in general imo too.


@lalinsky
With respect, “since July” is small potatoes. I reopened and landed a PR that was made originally in February 2025. I think that’s also small potatoes on the timescale of a project with the goals and scope of Zig.

4 Likes

In deed. But that works in both ways.

There is also the thing with different cultures and what is perceived as friendly and not here and there. I did not see “crashing out on the forum”. But I’m German and we are not known for sensitivity and good manners. So maybe it was me crashing out here. If so, it was not my intention.

We live in a time in which everybody firmly believes to be the sovereign master of truth and wisdom. Me included.

3 Likes

No, not all operating systems support poll.
Especially research OSes lack it more and more often since it maps badly to how modern IO works, since they all (EDIT: as in hardware) pretty much converged onto a ring design (the idea is similar to io_uring), unlike 40 years ago where it was a mess.
But even then, on quite a few which technically support polling but prefer completion based IO, the readiness based API is very often kinda bad and/or slow. Another example for that: z/OS which has it pretty much entirely for compatibility with libraries from other ecosystems (and because of it badly optimised).

1 Like

I can tell from experience, that any amount of contribution is useful. And they do listen to suggestions and design problem. For example, Im one of the people who went on and shared my concern about something lacking in the Io interface zsf-zulipchat and as you can see, they did take into consideration, the API hole I was facing with the Io interface, and if you look at the codeberg history it eventually led to a solution, in the form of Operation Operate and Batch so even if you don’t push code, or make a detailled pr, you could still share and voice your concern, and have them take it into consideration. They might ask you to make a pr, an issue, or they will do it themselves, so there’s hope

2 Likes

“Stretching yourself thin” does not have a corporate lens. Sure, one can apply a corporate interpretation to that, but one can do that to pretty much everything, be it meals, shoes, relationships, communication in general etc.

About that second to last sentence: Did you interpret this part of mine as “crashing out” somehow?
Because if you do, I don’t even know how to react to that.

4 Likes

To add to this, there are even situation where reactions from different cultures are fundamentally incompatible or create a problem from misunderstandings born out of different communication styles.

There are many reasons why people (especially business people) go courses to learn about stuff like this.

2 Likes

One thing that’s missing from this discussion is that if someone consistently does good work on std.Io while maintaining a positive attitude and without using LLMs, they will just be added to the core team. So far that hasn’t happened yet, but I bet it will soon.

9 Likes

no, sorry, that was an implicit dig at @lalinsky which was probably inappropriate, I apologize.

1 Like

I’m not sure you caught the exact meaning of my ‘as much information as possible’ comment. What I’m suggesting is that a) nothing you can do can avoid the need for a local workaround in the short term, that’s just the situation as it is and b) if you want to do the most possible to help the zig team solve it the right way, then showing them your PR and letting them decide when they get to it whether and how it should inform their final merged plan. Which is to say, you can’t know if the result can become a contribution to the final merged code but even then it could be a more precise contribution to the discussion than a forum post.

But it’s of course that takes time and it’s your prerogative what to do with your time. I’m just describing a different way to think about PRs, and I can’t even speak to whether the Zig team would think of it the same way as I do. Maybe you understood me perfectly well the first time, but I did want to say it more clearly than I did before.

2 Likes

Agree, not long ago I’ve made a Pr which hasn’t been merged but sparked a discussion about a missing variant of the implementation which led to another Pr by the person which knows more about it than I do, so any contribution, even the one that goes to the bin, can be useful.

1 Like