HashX: Incomplete error propagation on mprotect failure, segfault
This was found by @jnewsome in shadow simulations, where mprotect() was returning failure due to a memory optimization, and HashX oblivious to the failure proceeded to call into code which was never made executable. The resulting segfault appears at the very beginning of a dynamically allocated page.
The root cause is that hashx_compile returns void instead of propagating errors, so internally it discards an mprotect failure and hashx_make() returns 0 despite an opportunity to fail better.
The failure mode is still not great if we apply the obvious plumbing improvements to that error path, since we fail at solve/verify time rather than at setup time and PoW will never return any solutions. Since we don't have cancellation yet, this means a cpuworker will get tied up in an infinite loop too. Extra not good.
We might need to add an additional trial mprotect earlier on, when we can still fall back to the interpreted hashx, or do some deeper hackery. In addition this is getting complex enough that I want a unit test to go along with it. The best outcome would be a clean fallback from the compiled hashx to interpreted. A tor_assert() would be preferable to a segfault or an infinite loop but still bad.