Earlier quoted context omitted.
Where's the problem? Compiler will tell you what amount of stack a function will use, if it's inlined it may not tell you for that function, but it will tell you for the function the function was inlined to, which is what matters. If the language is complicated and has generics or whatever, the programmer will have to do more work to understand it. It's not a huge issue in C.
> Compiler will tell you what amount of stack a function will use If you ask a compiler how much stack a function will use the answer for a non-trivial compiler for a complicated language is always going to be 'it depends...'
Understanding thread stack sizes and how Alpine is different
61–70 of 81 posts
Re: Understanding thread stack sizes and how Alpine is different
#62Is Alpine using some new kernel? No, it's a Linux distribution that uses the Linux kernel, albeit with some unusual defaults.
Does Alpine not have any of the GNU userspace tools? Also no, there are plenty in the Alpine package repository.
Look, I get that GNU/Linux and ”GnU pLuS LiNuX" is a loaded term and has a lot of baggage, and that everyone would like to just be rid of the whole mess, but the characterization used here had me thinking that there was some other "Alpine kernel" experimental OS project that I had missed that had nothing to do with Alpine Linux.
The word "Linux" never once follows the word "Alpine" in this article, and it discusses overcommit mode as if it's a uniquely "GNU/Linux" thing. WTF does kernel overcommit have to do with GNU?
Please just call it what it is.
Re: Understanding thread stack sizes and how Alpine is different
#63 #include
void some_function(void) {
thread_local char scratchpad[500000];
memset(scratchpad, 'A', sizeof scratchpad);
}
As an important note, thread-local storage through this keyword still isn't supported on OpenBSD. It's a serious PITA.[——— also, copied from a reply I posted below: ———]
The autofree macro is wrong since __attribute__((cleanup)) expects a function that takes an additional level of pointer. In this case, it'll call "free(&scratchpad);". Which doesn't get you a compiler warning in C because passing a char ** as a void * is perfectly fine. But your heap is f*cked after this.
Correct way to do it is
void free2(char **p)
{
free(*p);
}
#define autofree __attribute__((cleanup(free2)))Re: Understanding thread stack sizes and how Alpine is different
#64Why would you overcomplicate your life and use something like the autofree example, that is not even portable, if you can use the heap which is simple to understand and do? I understand that if it is a hot function you may run into memory fragmentation/performance issues, but there are some many ways to deal with that with custom allocators if it truly is a problem . This is one of those perfect examples where simple…
It's also wrong since __attribute__((cleanup)) expects a function that takes an additional level of pointer. In this case, it'll call "free(&scratchpad);". Which doesn't get you a compiler warning in C because passing a char ** as a void * is perfectly fine. But your heap is f*cked after this.
Correct way to do it is
void free2(char **p)
{
free(*p);
}
#define autofree __attribute__((cleanup(free2)))Re: Understanding thread stack sizes and how Alpine is different
#65The distinction that's being characterized as "GNU/Linux" vs. just "Alpine" is confusing. Is Alpine using some new kernel? No, it's a Linux distribution that uses the Linux kernel, albeit with some unusual defaults. Does Alpine not have any of the GNU userspace tools? Also no, there are plenty in the Alpine package repository. Look, I get that GNU/Linux and ”GnU pLuS LiNuX" is a loaded term and has a lot of baggage,…
Kernel overcommit has nothing to do with GNU, but default stack size has a lot to do with which libc you use. Musl has a different default than glibc. Overcommit is mentioned because it is the justification for glibc having a large stack size by default. Musl has defaults that make fewer assumptions about how the system is configured.
Re: Understanding thread stack sizes and how Alpine is different
#66> In general, it is my opinion that if your program is crashing on Alpine, it is because your program is dependent on behavior that is not guaranteed to actually exist, which means your program is not actually portable. When it comes to this kind of dependency, the typical issue has to deal with the thread stack size limit. The wording sounds as if it is trying to assign blame for the problem. What, then, is the guar…
If you need a big stack, you can just ask pthread to give you one.
Re: Understanding thread stack sizes and how Alpine is different
#67In other words, use heap space and not stack space. This is pretty elementary in C programming.
It's a bit ridiculous to complicate recursive algorithms just because the stack sizes haven't been increased in the past 3 decades. Nowadays we have at least 48bit virtual address space available; what's the harm in giving each thread a full GB of stack?
Re: Understanding thread stack sizes and how Alpine is different
#68The distinction that's being characterized as "GNU/Linux" vs. just "Alpine" is confusing. Is Alpine using some new kernel? No, it's a Linux distribution that uses the Linux kernel, albeit with some unusual defaults. Does Alpine not have any of the GNU userspace tools? Also no, there are plenty in the Alpine package repository. Look, I get that GNU/Linux and ”GnU pLuS LiNuX" is a loaded term and has a lot of baggage,…
So in your view, having even a single GNU tool installed, or even available for installation, means you're using "GNU/Linux"? Alpine uses musl and busybox rather than the more common GNU equivalents. Kernel overcommit has nothing to do with GNU, but default stack size has a lot to do with which libc you use. Musl has a different default than glibc. Overcommit is mentioned because it is the justification for glibc hav…
I still think only referring to it as "Alpine" and not once calling it "Alpine Linux" is weird.
Re: Understanding thread stack sizes and how Alpine is different
#69In other words, use heap space and not stack space. This is pretty elementary in C programming.
That might have been true in the old days when memory wasn't the bottleneck, but in today's world where a cache miss is catastrophic, it makes MUCH more sense to use stack space where you can. This also has the side effect of facilitating idempotent functions and function purity in general. No sense in clinging to old world ideals when they no longer make sense.
But in the contemporary world, the trend is increasingly to transform functions to "async" forms where much of the functions' local state including return address is stored in heap-allocated space instead.
Re: Understanding thread stack sizes and how Alpine is different
#70I remember reading about arguments over whether Algol should permit recursive procedures, where one side of the argument was apparently claiming that they wouldn't be possible to implement. That seems pretty strange to modern ears, but maybe the underlying point was that it isn't possible to statically know how much stack size would be required. I suppose it wouldn't have been obvious then that if you fudge the issue…
It's not just that - if it were merely that you couldn't know the size statically, you could use dynamic memory allocation. The problem with that though, is that now every (not provably nonrecursive) function call can now fail with a memory allocation error, and if your language doesn't surface that to the caller, and (correctly) doesn't allow spurious errors to appear out of nowhere (cough every modern programming language cough cough), there's no way to handle that error.