I managed to track down the crash running javac in user-mode emulation. The problem is that we can have several threads which race in page_unprotect():
* threads A & B both try to do a write to a page with code in it at the same time (ie which we've made non-writeable, so SEGV) * they race into the signal handler with this faulting address * thread A happens to get to page_unprotect() first and takes the mmap lock, so thread B sits waiting for it to be done * A then finds the page, marks it PAGE_WRITE and mprotect()s it writable * A can then continue OK (returns from signal handler to retry the memory access) * ...but when B gets the mmap lock it finds that the page is already PAGE_WRITE, and so it exits page_unprotect() via the "not due to protected translation" code path, and wrongly delivers the signal to the guest rather than just retrying the access I'm not sure how best to fix this. We could make page_unprotect() say "if PAGE_WRITE is set, assume this call raced with another one and say 'this was caused by protected translation' without doing anything". But I have a feeling that will mean we could end up looping endlessly if we get a SEGV for a write to a writeable page (not sure when this could happen, but maybe alignment issues?). Anybody got a better idea? thanks -- PMM