manage: fix emergency buffer and north road calculation#993
Conversation
joemfb
left a comment
There was a problem hiding this comment.
u3_melt_all() / u3_meld_all() should be changed to lose and reallocate the emergency buffer (or simply not canonicalize it). Its purpose is defeated if it ends up structurally shared with any other part of the state.
| /* u3a_is_north(): yes if road [r] is north road. | ||
| */ | ||
| # define u3a_is_north(r) __((r)->cap_p > (r)->hat_p) | ||
| # define u3a_is_north(r) __((r)->mat_p > (r)->rut_p) |
There was a problem hiding this comment.
A road is north if the heap is low and the stack is high; south is opposite. This check has always been implemented using the innermost bounds of the stack ("cap") and heap ("hat").
The heap growing over the stack is guarded by explicit checks in the allocator, but the stack growing over the heap is not (the "cap" is constantly moving, so such checks have a measurable cost). Instead, a PROT_NONE guard page floats between the heap and the stack. Stores into it are caught by a global SIGSEGV handler and the page is repositioned if possible. If not the fault is handled with u3m_signal(c3__meme). In that state, the old implementation of u3a_is_north() will give the wrong answer, which wreaks havoc on refcounting and de/allocation logic.
This change makes u3a_is_north() robust against overflow states, by comparing the immutable outermost bounds of the heap ("rut") and stack ("mat").
| u3R->bug.mer = u3i_string( | ||
| "emergency buffer with sufficient space to cons the trace and bail" | ||
| u3R->bug.mer = u3i_tape( | ||
| "emergency buffer" |
There was a problem hiding this comment.
This is overkill, since at-most three cells are required for re-consing the bail mote and trace in u3m_bail(). At the same time, since this is a fresh road, we'll be allocating a full page of cells and putting the remainder in the cell pool. So I'm not sure if the difference matters.
Resolves #