While doing the rest of nommu support in netcat -L, I had some variant of: function() { int child, blah = 3;
for (;;) { crunch(blah); child = vfork(); if (child<1) break; } thingy(); execlp(stuff); } And gcc's optimizer went "blah isn't used anymore after the for loop, I'll trim the stack frame down so the return address in the call to thingy() in the child overwrites it, and then when vfork returns it's corrupted in the parent and the next call to crunch() goes bye-bye". Because gcc's optimizer does not understand vfork()'s impact on "liveness analysis". (You can think of vfork() as a setjmp that will fork() when it hits the next exec or exit, and then the parent process longjmp()s back to the stack until the child. But gcc's optimizer doesn't.) The fix is to add an unnecessary use of blah to the end of the function to let it know it's still %*#(%&& used, but then I need a GREAT BIG COMMENT to explain why so it isn't removed in future cleanup passes. And every other variable potentially has that same problem. As usual, I want to punch gcc's optimizer in the face and go "DO WHAT I TOLD YOU TO DO, DON'T MAKE STUFF UP!" but it never listens. (Do I have to start building everything with -O0? What optimization level gives me dead code elimination and nothing else?) Rob P.S. I'm always amused by the go/rust/swift developers who haven't hit their language with anything like the range of use cases you get in C, confidently stating that they have yet to see such strange corner cases in _their_ language yet. Uh-huh. There's a reason for that and it's probably not the one you think. _______________________________________________ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net