ocaml / ocamlfind

The OCaml findlib library manager
Other
30 stars 30 forks source link

ocamlfind infinite loop in package_deep_acenstors, after uTop called dont_load_deeply and list_packages #82

Open edwintorok opened 2 months ago

edwintorok commented 2 months ago

I noticed that my uTop hangs after typing #require sometimes, but not always. I've eventually tracked it down to an interaction between auto-completion, which lists available packages, and the execution of the require command itself, but adding locks didn't avoid the problem. Debugging this inside uTop was quite difficult since ^C didn't give me a decent stacktrace, but it was possible by installing a custom SIGUSR1 handler that called Prinexc.get_callstack: https://gist.github.com/edwintorok/0fddd73ae1b39dc0eaa8b7c08e4bfb83

I came up with this minimal repro that doesn't depend on utop:

#use "topfind"
let () =
  Printexc.record_backtrace true;
  Sys.catch_break true;
  Topfind.don't_load_deeply ["utop"];
  let (_: _ list) =  Fl_package_base.list_packages () in
  let (_: _ list) = Findlib.package_deep_ancestors ["byte";"toploop"] [] in
  ()
ocaml findlibtest.ml
^CInterrupted.
Raised by primitive operation at unknown location
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Stdlib__List.exists in file "list.ml", line 176, characters 12-15
Called from Fl_topo.Make.let_le in file "fl_topo.ml", line 191, characters 10-32
Called from Fl_package_base.add_relations.(fun) in file "fl_package_base.ml", line 276, characters 1-37
Called from Stdlib__List.iter in file "list.ml", line 112, characters 12-15
Called from Fl_package_base.add_all_relations.(fun) in file "fl_package_base.ml", line 305, characters 2-35
Re-raised at Fl_package_base.add_all_relations.(fun) in file "fl_package_base.ml", line 297, characters 14-32
Called from Stdlib__List.iter in file "list.ml", line 112, characters 12-15
Called from Fl_package_base.requires_deeply in file "fl_package_base.ml", line 389, characters 2-35
Called from <unknown> in file "./findlibtest.ml", line 7, characters 20-72
Called from Topeval.load_lambda in file "toplevel/byte/topeval.ml", line 93, characters 4-14
$ ocaml -version
The OCaml toplevel, version 5.2.0

$ ocamlfind query -l findlib             
package:     findlib
description: Package manager
version:     1.9.6
archive(s):  
linkopts:    
location:    /var/home/edwin/.opam/5.2.0+fp/lib/findlib

This doesn't seem to reproduce in other compiler switches, so probably something specific to the packages I have here. ocamlfind.list.txt opam.list.txt

gerdstolpmann commented 1 month ago

I cannot reproduce the problem (with the packages that happen to be on my laptop).

This could be because there is a loop in the package graph. I wonder, however, why findlib does not reject the loop (if this is the root cause).