5 ms·
I love to combine assertions with « restartability ». If you’re program has entered an unknown, failed state, just restart it from a known state. Even better
by iTokio 1mo ago
I love to combine assertions with « restartability ».
If you’re program has entered an unknown, failed state, just restart it from a known state.
Even better if you can divide a complex system in sub modules that can recover independently without bringing down the entire system.
Something like Erlang supervision tree. Or at least a systemd Restart=always service.
if your program is mostly stateless, and « restartable », it becomes fault tolerant, and you can use assertions liberally and easily avoid unknown/bad states.
Invariants can be enforced, and correctness preserved.
But an important question remains when an assertion is triggered, why invariants were violated?
We need to preserve context, and decide to handle or not this case.
That is easy to forget in code that is assertions oriented.
- delusional 1mo ago> We need to preserve context, and decide to handle or not this case. That is easy to forget in code that is assertions oriented. The old solution to that, which worked very well, was coredumps. The assertion fires and your program is taken down, but just before that we save out the entire memory area of your program. That way you can come in with a debugger later and poke around. People would often leave some memory areas (typically circular buffers) with debug values that would be useful in debugging. They'd never be used anywhere in the program, unless the programmer had to poke around manually. I've often wished this workflow was still considered high priority on modern runtimes.
- rramadass 1mo agoYou are very right. With linker maps, debug symbol files etc. we can get a good handle on what went wrong. > People would often leave some memory areas (typically circular buffers) with debug values that would be useful in debugging. They'd never be used anywhere in the program, unless the programmer had to poke around manually. In one Linux-based system i worked on, they had an area of memory between the heap and the stack where shared libraries are typically mapped in, sectioned off as a circular buffer via linker scripts for each module which was then used for all sorts of logging. A separate process would also map this memory area to provide a UI and also to write to disk. It was pretty neat and worked great.