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

I have an object that needs to maintain an open file handle. I wrote my code in a way that made sence to me, however when I try to call the GetBlocks() function in the following code I get a 'Bad File Descriptor' error.

Here is the code for the object:
package OEFSDevice; sub new { my $class = shift; my (%params) = @_; my $ref = { 'Device' => $params{'Device'}, }; print("Device: |" . $params{'Device'} . "|\n"); sysopen($ref->{'HANDLE'},$params{'Device'}, O_RDWR | O_SYNC) || re +turn 0; return bless($ref, $class); } sub GetBlocks($$$) { my $self = shift; my ($Offset, $Count, $Buffer) = @_; sysseek($self->{'HANDLE'},$Offset * 512,0) || return 0; sysread($self->{'HANDLE'},$$Buffer,$Count * 512) || return 0; return 1; } sub SetBlocks($$$) { my $self = shift; my ($Offset, $Count, $Buffer) = @_; sysseek($self->{'HANDLE'},$Offset * 512,0) || return 0; syswrite($self->{'HANDLE'},$$Buffer,$Count * 512) || return 0; return 1; } sub Close { my $self = shift; close($self->{'HANDLE'}); } sub DESTROY { Close(); } 1;

Replies are listed 'Best First'.
Re: Need object to retain open filehandle.
by ysth (Canon) on Jul 02, 2007 at 03:37 UTC
    Can't comment on your problem, but a few pieces of advice:

    Don't use prototypes. Not on methods and not on non-methods. There may be exceptions to this rule, but you won't stumble across them for a long time.

    Your DESTROY method is calling Close using a non-method call. Do

    my $self = shift; $self->Close();
    instead. Or just get rid of DESTROY altogether: perl will close the file for you when the object goes out of scope; the only reason to manually do it would be to take some action when close() gives an error.

      Thanx for most of the advice, but before I thank you for the prototype comment can you please explain it to me? What is wrong with using prototypes?

      In this case the functions are not only useless, but dangerous if they do not receive these 3 parameters. If you have better way to do them please explain?

      Thank you!

      --------------------------------------

      I would rather take 30 minutes to re-invent the wheel then take 30 days to learn how to use someone else's. Before pestering me about my re-invention prepare to defend yourself with a way of learning how to use the wheel in less time than it takes for me to make one, one that I might add is specialized to my specific task!

        A quick search pops up this discussion, which makes some good points. tchrist's article referred to there has moved but is still available here.
Re: Need object to retain open filehandle.
by TOD (Friar) on Jul 02, 2007 at 03:31 UTC
    i have no problem with getting your code to work. but i used a plain file to read from. are you trying to read from a device? i wonder whether sysopen is the right method to do so.

    --------------------------------
    masses are the opiate for religion.

      Figured out the problem. It had nothing to do with my object. I am using threads in my main script, the problem is when I turn my object into a shared object.

        I am using threads in my main script, the problem is when I turn my object into a shared object.

        How are you "turning the object into a shared object"?

        In general, this doesn't work.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

      Yes, I am using a device, a hard drive specifically. Strange that it worked for you, I did my own test to see if it was a problem with the functions, the storing of the file handle, or somewhere else. Basically I did a sysseek and sysread in the new function, it worked then failed later when getblocks was called, so the open file handle works fine in the constructor, but dies somewhere before I call getblocks.

      I also tried standard open,read,write,seek and got the same problem.

      I need to access devices (whole point of the code) and I need to use sysread and syswrite because I want to bypass the buffered IO.