egunnar has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks. I'm trying to capture an error if i run out of disk space. To test this (I've never done anything like this before) I have started a new shell (bash) and ran ulimit -f 10. I then wrote a dummy program (called lots_of_print.pl) to try and capture the error and print to stderr. However I'm not getting my program's error message but I'm getting a message from the OS or maybe from the perl interpreter (so I can tell ulimit worked). Any ideas what I'm doing wrong? Thanks for your help, Erik

here is my shell output
[egartz@localhost fullment_programs]$ ulimit -f 10 [egartz@localhost fullment_programs]$ ./lots_of_print.pl File size limit exceeded [egartz@localhost fullment_programs]$


here is my program
#!/usr/local/bin/perl -w use strict; open (LARGE_FILE, ">large_file.txt"); for ( 1 .. 10000){ print LARGE_FILE "dummy line...dummy line...dummy line...dummy + line...dummy line...dummy line...dummy line...\n" or print STDERR "i + caught the error!\n"; }

Replies are listed 'Best First'.
Re: perl/linux ulimit -f question
by jmcnamara (Monsignor) on Apr 03, 2006 at 13:48 UTC

    Most Linux systems have a /dev/full device that you can use for testing disk full scenarios.

    See the full manpage.

    --
    John.

Re: perl/linux ulimit -f question
by tirwhan (Abbot) on Apr 03, 2006 at 13:56 UTC

    Take a look at the manpage for setrlimit (which ulimit uses to implement it's functionality). On my system this says

    RLIMIT_FSIZE
    The maximum size of files that the process may create. Attempts to extend a file beyond this limit result in delivery of a SIGXFSZ signal. By default, this signal terminates a process, but a process can catch this signal instead, in which case the relevant system call (e.g., write(), truncate()) fails with the error EFBIG.

    So in order to prevent your program from terminating you need to catch the SIGXFSZ signal, either by setting local $SIG{XFSZ}=IGNORE or by doing something more fancy, aka

    local $SIG{XFSZ}=sub { print STDERR "Caught SIGXFSZ" };
    (BTW, jmcnamara's suggestion is a very good one and will also give you more realistic results than using ulimit, because ulimit will fail your process with an EFBIG error, whereas /dev/full returns ENOSPC, just as a full filesystem would).

    All dogma is stupid.
      thank you all for your help. i'm glad i'm now aware of /dev/full (it worked perfect for my testing). it seems like a good thing to be aware of for the future. regards, erik
Re: perl/linux ulimit -f question
by merlyn (Sage) on Apr 03, 2006 at 13:31 UTC
    When you exceed a limit (most of them, anyway), your program is immediately aborted. The shell notices this, and prints the message. There's no way your program could capture that message, as it has already been forcibly terminated.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.