Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

warn about indefinite loops that don't use remote calls #8639

Open
mikpe opened this issue Jul 3, 2024 · 3 comments
Open

warn about indefinite loops that don't use remote calls #8639

mikpe opened this issue Jul 3, 2024 · 3 comments
Labels
enhancement team:VM Assigned to OTP team VM

Comments

@mikpe
Copy link
Contributor

mikpe commented Jul 3, 2024

Is your feature request related to a problem? Please describe.
Consider systems that use live upgrades. There it's a problem when code performs indefinite loops using only local tailcalls, as a process running such a loop cannot be upgraded to new code unless it terminates the loop first. This may prevent the upgrade from succeeding.

Describe the solution you'd like
I'd like a compiler warning option, say warn_indefinite_local_loops, which discovers, conservatively, these cases and warns about them. The conditions should approximately be:

  • There's a loop in the control-flow graph. In the simplest case it's a function F/N which tailcalls itself, but it could be composed of multiple functions with a back-edge to a loop dominator.
  • The back-edge must be a local (non-remote) tailcall.
  • None of the arguments in the tailcall (back-edge) are a sub-term of the corresponding incoming arguments. This rules out finite structural-induction type loops.

Describe alternatives you've considered
None, as I consider the compiler to be the most appropriate place for non-trivial control-flow analysis.

Additional context
We've seen this problem occasionally in hand-crafted processes (that should arguably have been some gen_* behaviour), and most recently in a harmless-looking "wait for x to have occurred" synchronisation loop. In the latter case, the upgrade was a correction to the termination condition, but since tasks were already running the loop, they didn't see the correction and didn't terminate until we went in and killed them manually.

@frej
Copy link
Contributor

frej commented Jul 4, 2024

* There's a loop in the control-flow graph. In the simplest case it's a function F/N which tailcalls itself, but it could be composed of multiple functions with a back-edge to a loop dominator.

* The back-edge must be a local (non-remote) tailcall.

* None of the arguments in the tailcall (back-edge) are a sub-term of the corresponding incoming arguments. This rules out finite structural-induction type loops.

With only the three conditions above I'm afraid you'll get so many false positives that the warning (even if it not on by default) would be useless.

If you want to avoid false positives for structural-induction type loops, shouldn't you also consider things like a changing loop counter? Or more generally any conditional branches out of the loop? Should exception exits from the loop be considered? Even when extended along these lines (which is non-trivial), my guess is that you'll have a warning that either never triggers or triggers for almost all modules. Solving an undecidable problem, which this is, even approximately, is hard.

@mikpe
Copy link
Contributor Author

mikpe commented Jul 4, 2024

I'm not disputing that this is undecidable in general (it's equivalent to the halting problem), but it is also highly relevant (IMO) for Erlang, that's why I raised it.

@frej
Copy link
Contributor

frej commented Jul 4, 2024

I agree it's relevant, but as I said, I think designing warning heuristics that are actually useful isn't practical (famous last words).

@IngelaAndin IngelaAndin added the team:VM Assigned to OTP team VM label Jul 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement team:VM Assigned to OTP team VM
Projects
None yet
Development

No branches or pull requests

3 participants