After working at this, I finally found where it was happening, and a work-around.

I was checking all 517 http/s links in the documentation to see whether they are all live (not 404 and host found). For this I was using LibCurl::Easy.

The relevant bits of code was something like

for @links -> $link { # @links.elems = 517

    my $http = LibCurl::HTTP.new;

    try { $rv = $http.HEAD($link).perform.response-code }

    if $! { $rv = $http.error }

}

I had assumed that as soon as the $http went out of scope, it would be collected.

When I rewrote as

my $http = LibCurl::HTTP.new;

for @links -> link { ... }

then the program ran to completion without failing with 'too many file handles.


Now my question is this: Is this a problem with the LibCurl::Easy module, where I can raise an issue.

Or is this a more general Raku problem with objects not being garbage collected?

Richard


On 17/03/2021 17:55, Elizabeth Mattijsen wrote:
On 17 Mar 2021, at 18:45, Richard Hainsworth <rnhainswo...@gmail.com> wrote:

I have been running into this error: "Too many open files"

Sorry for the lack of detail. The problem is that the error comes up in odd 
places, so I have found it difficult to golf down into Raku program that always 
fails with this error.

When I separate out the code that leads to the error, and create another 
program, Raku handles it without difficulty. It seems to occur when there are a 
lot of moving parts, so to speak.

I am not explicitly opening file handles, but the software I have written is 
using the idiom

"some-filename.html".IO.spurt( $an-accumulated-string );

Obviously, filehandles are being opened under the hood. Having written a file, 
there is no need to reference it again, so I could close the filehandle.

I have been told that because of the way garbage handling is implemented, there 
is a problem with file handles.
That's should only happen if you specifically open a file to obtain an 
IO::Handle: if you don't close it yourself (e.g. via a LEAVE block like: LEAVE 
.close with $handle), *then* you run this risk, as the IO::Handle.DESTROY 
method *will* close the handle, but you cannot be sure as to when 
IO::Handle.DESTROY gets called.


If so, what is a safer idiom to use in place of and IO on a string, so that the 
handle can be closed immediately after use?
The "filelame".IO.spurt($string)" is the exact idiom to ensure that file 
handles are getting closed for you automatically.  And I've just checked the code: the OS file 
handle *is* specifically getting closed with an nqp::closefh($!PIO).  Specifically, the 
sequence is:

     my $PIO := nqp::open($path,$mode);
     nqp::writefh($PIO,nqp::decont(data));
     nqp::closefh($PIO);

Now, you can't get more succinct than that: it doesn't even open an IO::Handle 
at all!

The only thing I can think of at this moment, is that somehow nqp::closefh() is 
leaking?  Perhaps creating an issue for this, is in order!


Liz

Reply via email to