Phrase_from_file fails after 17 iterations

Hi, having an odd problem calling phrase_from_file in a loop.

consulted file:

get_neighbors(FileName, NbrInfos):-
    phrase_from_file(device_neighbors(NbrInfos), FileName), !.

called as:

process_nbrs_file(Switch):-
    get_neighbors(Switch, NbrInfos),
    do_stuff_with(Switch,NbrInfos).

main:-
    expand_file_name('*',Switches), 
    forall(member(Switch,Switches),
	   once(process_nbrs_file(Switch))).

Every file parses correctly individually but when called like this it stops on the 18th file.
I was guessing maybe a limit of 20 file descriptors but I can’t find any reference to that.
And phrase_from_file calls close (inside cleanup).
What I see when debugging is that device_neighbors when called on the 18th time gets an empty list as the DCG tail.

I can do them individually but there are hundreds so it slows the process down.

Happens on 9.0.4 and 8.4.2
Any help appreciated.

“Stops”? With what text output and/or exit code?

Try running on just that 18th file.

Stops → fails.
I’ve run it on all files and it succeeds if done individually.
Since the DCG list is empty the 18th time it will fail to parse and hence fail the forall.

Zero-in on the code line which fails, and determine why. Standard debugging.

There aren’t any lines that fail.
The parse works when done individually.
The debugging tells me that the contents of the file is missing.

If it fails, as you said, then it fails at a particular point.

So, identify that point. This is standard debugging.

I’ve identified the failure 3 times now!
When phrase_from_file calls device_neighbors the DCG list that should be the contents of the file is empty. It’s not failing in my code. Please read what I’ve written.

I was hoping there would be some deep prology reason why it couldn’t open another file or something.
On reflection, I’ll just submit a bug report.

In your bug report, please include a Minimal reproducible example - Wikipedia

Sorry to say this but I really don’t see enough evidence here to support that you have found a bug.


Some ideas.

Have you tried using gtrace/0 to debug the code?

e.g.

main:-
    gtrace,
    expand_file_name('*',Switches), 
    forall(member(Switch,Switches),
	   once(process_nbrs_file(Switch))).
  1. Did you closely read the documentation for expand_file_name/2

Unify List with a sorted list of files or directories matching WildCard.

I suspect that the list contains directories such as . and .., make sense?

Can you show us what is in the list Switches before forall/2.

main:-
    expand_file_name('*',Switches), 
    print_term(Switches,[]),
    forall(member(Switch,Switches),
	   once(process_nbrs_file(Switch))).

I have not tried this but you should get the idea. use file_exists/1

:- use_module(library(file_systems)).

main:-
    expand_file_name('*',Switches), 
    print_term(Switches,[]),
    forall(
        member(Switch,Switches),
       (
            file_exists(Switch),
	        once(process_nbrs_file(Switch))
        ;
            true
       )
    ).

No, there’s no bug, not in swipl (not in my code either).
A couple of the input files had been truncated and it never occured to me to check for that before running it.

I was using gtrace, but I’ve never been able to navigate the stack without getting lost.

Anway, it was a stupid mistake not to look outside the code. Somehow those are usually the ones that end up embarassing me.