Wrap Parsing_heaps.add with with_no_cancellations
Wrap Parsing_heaps.add with with_no_cancellations

Summary:
This fixes the merge and check internal errors of `Requires_not_found` and `Sig_requires_not_found` that have been occurring since the rollout of saved state.

We've been getting steady reports of Flow failing with an internal merge error and the message exception `Requires_not_found` or `Sig_requires_not_found`. Because these errors only cropped up occasionally, it was difficult to find a root cause. I inspected the logs and didn't see anything suspicious. So, I resorted to a careful reading of the relevant code, and while I found and fixed a different root cause for this same issue (D23110950 (https://github.com/facebook/flow/commit/314be772c55a8e14a1621fad7d9a632b90f81588)), it didn't match the logs from the reports I was seeing, and the errors persisted.

Eventually one of the reporters was able to send me repro steps that worked intermittently, and from there I was able to refine them until I had a consistent repro. That allowed me to narrow in on the root cause for this bug:

* Flow starts doing a recheck after a saved state init, but is interrupted during the parsing phase kicked off by `ensure_parsed` by changes on disk which the file watcher reports.
  * This kicks off a cancellation of the recheck in progress.
  * Workers are canceled via the cancellation mechanism in hh_shared.c. This mechanism sets a bit which causes calls into the shared heap to raise an exception.
  * This can cause the worker process to exit in the middle of a call to [`ParsingHeaps.add`](https://github.com/facebook/flow/blob/ab1bb3b938b5e633ea177425171548b6c5acfcc0/src/state/heaps/parsing/parsing_heaps.ml#L192), resulting in the AST for a file being written to the shared heap, but not other parsing artifacts.
  * When we roll back the partial recheck, we don't roll back anything done by [`ensure_parsed`](https://github.com/facebook/flow/blob/ab1bb3b938b5e633ea177425171548b6c5acfcc0/src/parsing/parsing_service_js.ml#L879-L881) (see the linked comment).
* Then we start a new recheck with the additional files:
  * We call `ensure_parsed` once again. It determines which files need to be parsed by [checking which ones have ASTs stored](https://github.com/facebook/flow/blob/ab1bb3b938b5e633ea177425171548b6c5acfcc0/src/parsing/parsing_service_js.ml#L891).
  * Because the call to `add` was interrupted in the last recheck, it's possible for some files to have the ASTs stored, but not all of the other parsing artifacts. Such files are not parsed again, since `ensure_parsed` sees that the AST is present.
  * Later in the recheck, when we need, for example, the sig file sig, it's not available and we get an internal merge or check error.

The solution is fairly straightforward: Do not let a cancellation occur in the middle of the `add` operation. The `with_no_cancellations` utility sets a bit that prevents cancellations from occurring, and then unsets it at the end. This ensures that adds to the parsing heaps are atomic. We rely on the invariant that if one parsing artifact is present for a given file, that they all are. This change ensures that this invariant holds.

Reviewed By: mroch, samwgoldman

Differential Revision: D24086782

fbshipit-source-id: 2a3361efb32ad61b8b3e3fe5b1462dec5214cc1d

nmote/flow,nmote/flow,nmote/flow,nmote/flow,nmote/flow,nmote/flow,nmote/flow