Live data from Hacker News

C stdlib isn't threadsafe and even safe Rust didn't save us

edgedb.com

131–140 of 370 posts

Re: C stdlib isn't threadsafe and even safe Rust didn't save us

#131

Earlier quoted context omitted.

By definition, a "reentrant function" is a function that may be invoked even when it has not returned yet from a previous invocation. So a non-reentrant function is a function that may not be invoked again between a previous invocation and returning from that invocation. When a function may be invoked from different threads, then it is certain that sometimes it will be invoked by a thread before returning from a prev…

Who has a signal safe malloc?

POSIX does not require malloc to be signal safe.

Therefore I do not think that anyone has bothered to implement a signal-safe malloc, as this is likely to be complicated.

Allocating memory in a signal handler makes no sense in a well designed program, so not being allowed to use malloc and related functions is not a problem.

Re: C stdlib isn't threadsafe and even safe Rust didn't save us

#132
post #5

The major takeaway from this is that Rust will be making environment setters unsafe in the next edition. With luck, this will filter down into crates that trigger these crashes ( https://github.com/alexcrichton/openssl-probe/issues/30 filed upstream in the meantime).

But that won't actually fix the underlying problem, namely that getenv and setenv (or unsetenv, probably) cannot safely be called from different threads. It seems like the only reliable way to fix this is to change these functions so that they exclusively acquire a mutex.

No amount of locking can make the getenv API thread-safe, because it returns a pointer which gets invalidated by setenv, but lacks a way to release ownership over it and unblock setenv safely (or to free a returned copy).

So setenv's existence makes getenv inherently unsafe unless you can ensure the entire application is at a safe point to use them.

Re: C stdlib isn't threadsafe and even safe Rust didn't save us

#133
post #127

Earlier quoted context omitted.

I mean, yes, we're in "violent agreement" there. It's nice that libc squirrels away a copy and gives you a `getenv()` function with a string lookup, but… setenv… that was just a horrible idea. It's not really wrong to view it as a tool that allows you to muck around with main()'s local variables. Which to me sounds like one should take a shower after using it ;D (Ed.: the man page should say "you are required to take…

Oops, didn't mean to come across as disagreeing at all, more of a "yes, and ".

Ah, after rereading I think I accidentally read that in, sorry

Re: C stdlib isn't threadsafe and even safe Rust didn't save us

#134
post #12

Mutable global state is evil. Friends don’t let friends use mutable global state. I hate envvars. It’s “the Linux way”. I avoid them like the plague. A++ strong recommend. libc is terrible. The world needs to move on.

> Mutable global state is evil. Friends don’t let friends use mutable global state. Throw away your CPU and RAM then.

I can not possibly roll my eyes hard enough.

Go ahead and write lots of mutable global statics. But when your program crashes randomly and you need my help to debug and it is, once again, a global mutable then you have to perform a walk of shame.

Re: C stdlib isn't threadsafe and even safe Rust didn't save us

#135
post #85

This reminded me of that whole "12-factor app" movement, which several of my former coworkers had really bought into. One of the "factors" is that apps should be configured by environment variables. I always thought this was kinda foolish: your configuration method is a flat-namespace basked of stringly-typed values. The perils of getenv()/setenv()/environ are also, I think, a great argument against using env vars fo…

getenv() is perfectly fine, it's setenv() that is the problem. Which in theory this wouldn't be using since the env would be set up prior to starting that mystical app.

But yes, a flat namespace, with string values, shared as a free-for-all with who knows what libraries and modules you're loading… that's not a good idea even if it didn't have safety issues in setenv().

Re: C stdlib isn't threadsafe and even safe Rust didn't save us

#136

Earlier quoted context omitted.

This is not unusual at all. Windows allowed it for years before Linux came along. It was also true of some other *nix systems - IIRC, Ultrix (DEC) allowed this, and so did Dynix (Sequent). *BSD allows it too, or used as of 2022. What is unusual about Linux is that it guarantees a syscall ABI, meaning that if you follow it, you can make a system call "portably" across "any" version of Linux.

Sure, I’m speaking about platforms that are relevant today, not historical ones. Windows, MacOS, {Free,Open,Net}BSD, Solaris, illumos, none of these do.

It's quite easy to find out the actual situation on this since Go decided to do it their way. Last I checked, OpenBSD is the only OS where they go through libc, but I haven't really kept up.

Re: C stdlib isn't threadsafe and even safe Rust didn't save us

#137
post #121

Earlier quoted context omitted.

One of the major differences between X Window and the win32 GUI APIs is that the windows one builds in thread safety, and it cannot be removed. This means that you pay the price of mutexes and the like (what the windows world likes to call "critical sections"), even if you have a single threaded GUI. X Window, on the other hand, decided to do nothing about threads at all, leaving it up to the application. 30 years af…

Yet 30 years later people are calling setenv()/getenv() from different threads even though "it is known" that it crashes. For whatever reason the lesson from GUIs doesn't apply here.

Judging from a lot of the comments in this thread, the idea that there could even be parts of the *POSIX API* that are not thread-safe seems like an idea that hasn't even occured to a lot of (younger?) programmers ...

Re: C stdlib isn't threadsafe and even safe Rust didn't save us

#138

Earlier quoted context omitted.

Sure, I’m speaking about platforms that are relevant today, not historical ones. Windows, MacOS, {Free,Open,Net}BSD, Solaris, illumos, none of these do.

It's quite easy to find out the actual situation on this since Go decided to do it their way. Last I checked, OpenBSD is the only OS where they go through libc, but I haven't really kept up.

In my understanding, Go initially disregarded various platforms' rules here, and have ended up walking it back. I could be wrong though.

It's hard to find good details here, but here's a mailing list thread from 2019 mentioning libc usage: https://groups.google.com/g/golang-nuts/c/uX8eUeyuuAY/m/Cfhl...

> On Solaris (and Windows), and more recently in macOS as well we link with libc (or equivalent).

> Go used to do raw system calls on macOS, and binaries were occasionally broken by kernel updates. Now Go uses libc on macOS.

Re: C stdlib isn't threadsafe and even safe Rust didn't save us

#139
post #92

Earlier quoted context omitted.

The underlying problem is that setenv is mutable global state and should never have existed

The process's current directory is mutable global state as well, and yet chdir(2) is thread-safe.

chdir is thread-safe, but interacting with the current directory in any context other than parsing command-line arguments is still nearly always a mistake. Everything past a program's entry point should be working exclusively in absolute paths.

Re: C stdlib isn't threadsafe and even safe Rust didn't save us

#140

Earlier quoted context omitted.

It's quite easy to find out the actual situation on this since Go decided to do it their way. Last I checked, OpenBSD is the only OS where they go through libc, but I haven't really kept up.

In my understanding, Go initially disregarded various platforms' rules here, and have ended up walking it back. I could be wrong though. It's hard to find good details here, but here's a mailing list thread from 2019 mentioning libc usage: https://groups.google.com/g/golang-nuts/c/uX8eUeyuuAY/m/Cfhl... > On Solaris (and Windows), and more recently in macOS as well we link with libc (or equivalent). > Go used to do ra…

Yep, in 2022 it finally started using libc on *BSD too.

But ... there's a difference between being able to do direct syscalls via asm, and them being portable across kernel versions, which is what this subthread was about.

Granted, most people want version portability, but still on a technical level, it's not the same thing.

Post reply on HN