<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hacker News: fonheponho</title><link>https://news.ycombinator.com/user?id=fonheponho</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Sat, 13 Jun 2026 16:22:07 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=fonheponho" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by fonheponho in "Moving beyond fork() + exec()"]]></title><description><![CDATA[
<p>> The elegance of the fork() + exec() model is that every kind of configuration can be done after the fork using all the usual APIs.<p>Unfortunately, the opposite is true, when the parent process is multi-threaded. In the child process, only one thread exists (the thread returning from fork()), but the memory is an exact copy of the parent's. As a result, the child may inherit locks (resident in memory) that are in acquired state, but have no owner threads -- the threads that are responsible for eventually releasing those locks in the child's copy of the process memory do not exist in the child. If the single thread in the child process (returning from fork()) attempts to take such a lock (before exec), it deadlocks. This is why POSIX says that only async-signal-safe functions may be called in a child process, between fork and exec. And then, for example, "malloc" is not such a function (at least per POSIX), so the fork-to-exec environment in the child process is an extremely uncomfortable one. You've got to preallocate everything in the parent, can't report errors to stderr, etc.<p><a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/fork.html" rel="nofollow">https://pubs.opengroup.org/onlinepubs/9799919799/functions/f...</a><p><a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.html#tag_16_04_03_03" rel="nofollow">https://pubs.opengroup.org/onlinepubs/9799919799/functions/V...</a><p>The fork(2) Linux manual page spells out the sam restriction.<p><a href="https://man7.org/linux/man-pages/man2/fork.2.html" rel="nofollow">https://man7.org/linux/man-pages/man2/fork.2.html</a><p><a href="https://man7.org/linux/man-pages/man7/signal-safety.7.html" rel="nofollow">https://man7.org/linux/man-pages/man7/signal-safety.7.html</a><p>"pthread_atfork" exists, but is effectively unusable.<p><a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_atfork.html" rel="nofollow">https://pubs.opengroup.org/onlinepubs/9799919799/functions/p...</a></p>
]]></description><pubDate>Sun, 07 Jun 2026 13:48:32 +0000</pubDate><link>https://news.ycombinator.com/item?id=48434852</link><dc:creator>fonheponho</dc:creator><comments>https://news.ycombinator.com/item?id=48434852</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48434852</guid></item><item><title><![CDATA[New comment by fonheponho in "I hate: Programming Wayland applications"]]></title><description><![CDATA[
<p>I have no love lost for Wayland, but this:<p>>  Make easy things easy. Make hard things doable.<p>is generally unachievable. Instead, pick one:<p>- easy things easy, hard things impossible<p>- easy things tedious, hard things possible<p>(Unless you want to maintain two sets of interfaces in parallel.)</p>
]]></description><pubDate>Sun, 22 Mar 2026 16:58:37 +0000</pubDate><link>https://news.ycombinator.com/item?id=47479548</link><dc:creator>fonheponho</dc:creator><comments>https://news.ycombinator.com/item?id=47479548</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47479548</guid></item><item><title><![CDATA[New comment by fonheponho in "My first patch to the Linux kernel"]]></title><description><![CDATA[
<p>> It does not matter which is the relationship between the sizes of such types, there will always be values of the operand that cannot be represented in the result.<p>It's not that bad actually; not "always". The only nontrivial case is when, as a part of the <i>usual arithmetic conversions</i>, you (perhaps unwittingly) convert a signed integer type to an unsigned integer type [*], and the original value was negative.<p>[*] This can happen in two cases (paraphrasing the standard):<p>- if the operand that has unsigned integer type has rank greater than or
equal to the rank of the signed integer type of the other operand,<p>- if the operand that has signed integer type has rank greater than or
equal to the rank of the unsigned integer type of the other operand, but the signed integer type cannot represent all values of the unsigned integer type.<p>Examples: (a) "unsigned int" vs. "signed int"; (b) "long signed int" vs. "unsigned int" in a POSIX ILP32 programming environment. Under (a), you get conversion to "unsigned int"; under (b), you get conversion (for both operands) to "long unsigned int".<p>Section "3.2 Conversions | 3.2.1 Arithmetic operands | 3.2.1.1 Characters, and integers" in the C89 Rationale <<a href="https://www.open-std.org/Jtc1/sc22/WG14/www/C89Rationale.pdf" rel="nofollow">https://www.open-std.org/Jtc1/sc22/WG14/www/C89Rationale.pdf</a>> is worth reading. (An updated version of the same section is included in the C99 Rationale <<a href="https://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf" rel="nofollow">https://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.1...</a>> under 6.3.1.1.)<p>It deals precisely with the problem highlighted in the blog post. I'll quote just the beginning and the end:<p>> Since the publication of K&R, a serious divergence has occurred among implementations of C in the evolution of integral promotion rules. Implementations fall into two major camps, which may be characterized as <i>unsigned preserving</i> and <i>value preserving</i>. [...]<p>> The unsigned preserving rules greatly increase the number of situations where unsigned int confronts signed int to yield a questionably signed result, whereas the value preserving rules minimize such confrontations. Thus, the value preserving rules were considered to be safer for the novice, or unwary, programmer. After much discussion, the Committee decided in favor of value preserving rules, despite the fact that the UNIX C compilers had evolved in the direction of unsigned preserving.<p>> QUIET CHANGE -- A program that depends upon unsigned preserving arithmetic conversions will behave diﬀerently, probably without complaint. This is considered the most serious semantic change made by the Committee to a widespread current practice.</p>
]]></description><pubDate>Sun, 22 Mar 2026 16:44:30 +0000</pubDate><link>https://news.ycombinator.com/item?id=47479366</link><dc:creator>fonheponho</dc:creator><comments>https://news.ycombinator.com/item?id=47479366</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47479366</guid></item><item><title><![CDATA[New comment by fonheponho in "My first patch to the Linux kernel"]]></title><description><![CDATA[
<p>Everybody seems to be missing the forest for the trees on this.<p>There is absolutely no "sign extension" in the C standard (go ahead, search it). "Sign extension" is a feature of some assembly instructions on some architectures, but C has nothing to do with it.<p>Citing integer promotion from the standard is justified, but it's just one part (perhaps even the smaller part) of the picture. The crucial bit is not quoted in the article: the specification of "Bitwise shift operators". Namely<p>> The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. [...]<p>> The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1×2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1×2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.<p>What happens here is that "base2" (of type uint8_t, which is "unsigned char" in this environment) gets promoted to "int", and then left-shifted by 24 bits. You get <i>undefined behavior</i> because, while "base2" (after promotion) has a signed type ("int") and nonnegative value, E1×2^E2 (i.e., base2 × 2^24) is <i>NOT</i> representable in the result type ("int").<p>What happens during the conversion to "uint64_t" <i>afterwards</i> is irrelevant; even the particulars of the sign bit of "int", and how you end up with a negative "int" from the shift, are irrelevant; you got your UB <i>right inside</i> the invalid left-shift. How said UB happens to materialize on this particular C implementation may perhaps be explained in terms of sign extension of the underlying ISA -- but do that <i>separately</i>; be absolutely clear about what is what.<p>The article fails to mention the root cause (violating the rules for the bitwise left-shift operator) and fails to name the key consequence (undefined behavior); instead, it leads with not-a-thing ("sign-extension bug in C"). I'm displeased.<p>BTW this bug (invalid left shift of a signed integer) is common, sadly.</p>
]]></description><pubDate>Sun, 22 Mar 2026 11:44:07 +0000</pubDate><link>https://news.ycombinator.com/item?id=47476512</link><dc:creator>fonheponho</dc:creator><comments>https://news.ycombinator.com/item?id=47476512</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47476512</guid></item><item><title><![CDATA[New comment by fonheponho in "Terence Tao, at 8 years old (1984) [pdf]"]]></title><description><![CDATA[
<p>One of the most fascinating and <i>moving</i> writings I've read in my life.</p>
]]></description><pubDate>Tue, 24 Feb 2026 13:43:09 +0000</pubDate><link>https://news.ycombinator.com/item?id=47137070</link><dc:creator>fonheponho</dc:creator><comments>https://news.ycombinator.com/item?id=47137070</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47137070</guid></item><item><title><![CDATA[New comment by fonheponho in "A header-only C vector database library"]]></title><description><![CDATA[
<p>Exactly; I can't understand this obsession with header-only C "libraries".</p>
]]></description><pubDate>Sat, 14 Feb 2026 21:17:03 +0000</pubDate><link>https://news.ycombinator.com/item?id=47018472</link><dc:creator>fonheponho</dc:creator><comments>https://news.ycombinator.com/item?id=47018472</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=47018472</guid></item></channel></rss>