9 ms·
Never thought of that solution to segfaults before. Great trick for writing bug-free programs, going to go integrate that into all my code now.
by coldpie 6y ago
Never thought of that solution to segfaults before. Great trick for writing bug-free programs, going to go integrate that into all my code now.
- gowld 6y agoThis a standard technique for recovering from a memory violation in a non-critical function. The proper way to handle it is to save any transient data and restart the program.
- mnw21cam 6y agoAnd validate the transient data really carefully when you load it back in.
- Elph0 6y agoDon't forget to also catch other sigs.
- majewsky 6y agoMost of my signal handlers work just fine, but for some reason I cannot get the unit tests for SIGKILL and SIGSTOP green.
- segfaultbuserr 6y agoSome programs catch SIGSEGV and automatically prints out the stack trace and starts a debugger for you.
- sp332 6y agoOn Error Resume Next
- tonyarkles 6y agoThanks for the flashbacks!
- underdeserver 6y agoI still shudder at this.
- bigbizisverywyz 6y agoI still remember getting a support call communicated on to myself and a colleague when we were driving on-route to another client. colleague: "Caller says she's getting an error 'No Resumé' ?!?" us: ... huh?..... it is a document management system, but still ... . time passes . . me: Oh! On Error No Resumé us: much hilarity. No Resumé indeed.
- tonyarkles 6y agoNote that x86 has variable-length instructions, so incrementing RIP by 10 will not, in general, do what you want it to do. The author basically put in a nop slide[1] to ensure that that would work. Buuuuuut I’m pretty sure you could parse ELF debug symbols and effectively calculate the address of the next logical C instruction to execute :D Terrifying but fun! [1] https://en.wikipedia.org/wiki/NOP_slide https://en.wikipedia.org/wiki/NOP_slide
- loeg 6y agoOr decode the x86 stream to find the next instruction. :-) Next C statement is pretty cute, though.
- matja 6y agoInteresting problem - what's the shortest C function that takes a pointer to bytes and returns the length of the x86-64 instruction there? (and how many hours would it take to code it)
- loeg 6y agoStart here and minimize as you see fit: https://intelxed.github.io/ref-manual/group__DEC.html#ga4bef6152f61997a47c4e0fe4327a3254 https://intelxed.github.io/ref-manual/group__DEC.html#ga4bef...
- mhh__ 6y agoThe cheating way is probably to do this https://www.blackhat.com/docs/us-17/thursday/us-17-Domas-Breaking-The-x86-ISA.pdf https://www.blackhat.com/docs/us-17/thursday/us-17-Domas-Bre... (page ~71) i.e. shift across an instruction boundary.
- kccqzy 6y agoPut it on a page boundary. Make sure the next page isn't accessible. Analyze the resulting page fault.
- nilsb 6y ago
- tom_mellior 6y agoYou're joking, but this can be used in a semi-practical way to keep programs alive and mostly functioning, see http://people.csail.mit.edu/rinard/paper/pldi14.pdf http://people.csail.mit.edu/rinard/paper/pldi14.pdf for instance. The idea here is that you catch certain faulting operations and drop/fix them: segfaulting store? ignore! segfaulting read? manufacture a result value of 0, it's usually not too wrong. And by using LD_PRELOAD magic, this can even be retrofitted onto existing applications without changing or recompiling them.
- RMPR 6y agoSignals always seem (at least to me) to be an early implementation of exceptions
- monocasa 6y agoSort of? They're really an implementation of interrupts, but sitting on the kernel/user boundary rather than the hardware/kernel boundary. It's a hold over from when a process was really thought of as closer to a virtualized computer rather than a distinct concept in it's own right. And it's not uncommon for the interrupts managing CPU faults to be called exceptions https://wiki.osdev.org/Exceptions https://wiki.osdev.org/Exceptions , so their nomenclature does converge if you squint hard enough.
- Animats 6y ago"It's not uncommon for the interrupts managing CPU faults to be called exceptions, so their nomenclature does converge..." An interrupt and a CPU exception are different things. UNIX treats them similarly because the PDP-11 did. An interrupt is something outside the CPU wanting to be serviced, like an I/O completion. An interrupt can be deferred during a critical section, which is what "preventing interrupts" does. Some machines direct interrupts to one of many CPUs, so whoever is free can handle I/O. Interrupts have priorities, queuing, and are handled like events on a queue. A hardware exception is the CPU doing something that stops execution. Inaccessible memory - could be the need to page something in from disk, or a program error. The OS has to decide that. Floating point overflow. Divide by zero. An illegal instruction. The CPU can't continue. So exceptions cannot be deferred, even if in a critical section. The CPU that raised the exception must handle the exception; it can't be handled by another CPU. UNIX/Linux signals are rarely used for I/O completions in user space, but that is supported. See "aio".[1] Apparently Oracle uses this. [1] https://man7.org/linux/man-pages/man7/aio.7.html https://man7.org/linux/man-pages/man7/aio.7.html
- fanf2 6y agoThe original Bourne shell trapped SEGV (which it called MEMF) as part of its memory management strategy - https://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/fault.c https://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd...
- jeffffff 6y agomost modern concurrent copying garbage collectors use memory protection and sigsegv handlers to avoid the need for locking
- chrisseaton 6y agoAlmost all language runtimes trap SEGV for memory management and other services.
- simias 6y agoIf you really just want the program to continue operating on dereferencing NULL pointers (and assuming that a NULL pointer is a pointer to address 0 in the VM, which is a risky assumption to make) you can generally convince the OS to map address 0 to something valid, therefore making the access Just Work. Beyond that there are sometimes very valid reasons for allowing segfaults to occur in certain conditions and catching/patching them. For instance in an emulator's dynamic recompiler you could optimize your generated code by assuming that most memory accesses target the emulated RAM region (generally a reasonable assuption). Then you map the RAM buffer in such a way that if it turns out that the emulated program was actually attempting to access an address outside of RAM a memory fault occurs, which you can then catch and recompile the offending code block with a slower but more comprehensive address decode.
- coldpie 6y ago> If you really just want the program to continue operating on dereferencing NULL pointers you can generally convince the OS to map address 0 to something valid, therefore making the access Just Work. Yeah yeah yeah but this ALSO fixes use-after-free bugs! Really an amazing little trick, I wonder why compilers don't just do it automatically.
- pas 6y agoSee also how the JVM uses sigsegv signals for synchronizing safepoints for multiple threads: https://www.ateam-oracle.com/why-am-i-seeing-sigsegv-when-i-strace-a-java-application-on-linux https://www.ateam-oracle.com/why-am-i-seeing-sigsegv-when-i-...
- miohtama 6y agoThis is the old model made popular by Visual Basic. ON ERROR RESUME NEXT
- nialv7 6y agoYou can even do user-space on-demand paging with segfault handlers. Though there is a more modern solution for this: https://man7.org/linux/man-pages/man2/userfaultfd.2.html https://man7.org/linux/man-pages/man2/userfaultfd.2.html