Fix stale PicoSAT literal pointer crash under multi-threaded solve#831
Open
GregoryMorse wants to merge 1 commit into
Open
Fix stale PicoSAT literal pointer crash under multi-threaded solve#831GregoryMorse wants to merge 1 commit into
GregoryMorse wants to merge 1 commit into
Conversation
… Windows PicoSAT's inc_max_var() can realloc ps->lits when new variables are encountered mid-clause. Although fix_added_lits() patches buffered Lit* pointers in ps->added, the realloc is layout-sensitive: under heavy 8-thread allocation pressure the patch can miss a pointer, causing a dereference of a stale/corrupt Lit* in trivial_clause(). Fix: pre-register all variables with picosat_inc_max_var() before any picosat_add(...literal...) opens a clause, so ps->lits is fully grown before any Lit* pointers are buffered. Added: - register_lit_to_picovar() — registers a variable with PicoSAT without incrementing picolits_added (used during pre-registration) - pre_register_picosat_vars() — walks watched clauses and pre- registers all variables via register_lit_to_picovar() - Called at all three PicoSAT call sites before clause construction - release_assert in lit_to_picolit() that the variable was pre- registered, so any future pre-pass mismatch is caught immediately rather than manifesting as a rare heap crash Also: skip red binary watches in pre-registration (matching the filter in add_cls_to_picosat_definable), and reset picosat on added==0 in the definable paths to avoid accumulating unused vars.
Author
|
Fixes #830 |
Author
|
I have now run it for many hours over many various large instances and it is finally observably stable. I don't think this is Windows only and it is bizarre that it has not been observed previously. It can be that threads>=8 and realloc on linux are less likely to change allocation addresses. Picosat depends on realloc and pointer delta adjustments. Picosat is fragile and too address-sensitive. The fix here is a clean way around having to worry about it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PicoSAT's inc_max_var() can realloc ps->lits when new variables are encountered mid-clause. Although fix_added_lits() patches buffered Lit* pointers in ps->added, the realloc is layout-sensitive: under heavy 8-thread allocation pressure the patch can miss a pointer, causing a dereference of a stale/corrupt Lit* in trivial_clause().
Fix: pre-register all variables with picosat_inc_max_var() before any picosat_add(...literal...) opens a clause, so ps->lits is fully grown before any Lit* pointers are buffered. Added:
Also: skip red binary watches in pre-registration (matching the filter in add_cls_to_picosat_definable), and reset picosat on added==0 in the definable paths to avoid accumulating unused vars.