Get "Inappropriate ioctl for device" when using Perl

133 Views Asked by At

I've been strugging with this for a while and am not fluent with perl's core object system. This is a simplified part of a Larger Project where the problem occurs. I'm trying to write a class wrapping another class that outputs a .xlsx spreadsheet file onto disk. This one will work unless I include the die statement in the do_something subroutine. If I include the die statement it will cease but the .xlsx file will still be written onto disc up to the point of the die statement. It will not include the line from # Doesn't write. If I omit the die statement it will work exactly as expected, printing everything and closing gracefully.

What causes this "ioctl" error and how do I fix it? This fails on my Larger Project and will output the file to disc but not include the line written from the subroutine even without the die statement. Any help would be appreciated. Thanks!

#!/usr/bin/perl

package TestClass;

use Excel::Writer::XLSX;
use POSIX qw(strftime);
use Data::Dumper;

use strict;
use diagnostics;

sub new{
    my $class = shift;

    my $workbook = Excel::Writer::XLSX->new('test.xlsx');
    my $worksheet = $workbook->add_worksheet('demo');

    my $format = $workbook->add_format(
    color => 'black',
    bold => 1
    );
    
    my $self = {
    format => $format,
    workbook => $workbook,
    worksheet => $worksheet
    };
    bless $self, $class;

    $worksheet->merge_range( 0,0, 0,2, (strftime '%F %I:%M %P', localtime), $format );
    
#    $self->{worksheet}->write( 2,2, "Check", $format );
    $worksheet->write( 2,2, "Check", $format );
    &do_something( $self, 3,3, "Mate" );           # Main problem
    $worksheet->write( 4,4, "Match", $format );    # Doesn't write with 'die'

    $workbook->close();
    
    return $class;
}

sub do_something{
    my ( $self, $y, $x, $txt ) = @_;

    print Dumper( $self->{worksheet} ), "\n";
    print ref( $self->{worksheet} ), "\n\n";
# Line below writes but dies.
    $self->{worksheet}->write( $y,$x, $txt, $self->{format} ) or die "Didn't work: $!";
    
    return 1;
}


1;

Error message when run:

Uncaught exception from user code:
    Didn't work: Inappropriate ioctl for device at ./TestClass.pm line 47.
    TestClass::do_something(TestClass=HASH(0x55c438170d88), 3, 3, "Mate") called at ./TestClass.pm line 33
    TestClass::new("TestClass") called at -e line 1

Invocation with output from Dumper() and ref():

sudo perl -e "require './TestClass.pm';TestClass->new();"
$VAR1 = bless( {
                 '_dim_rowmin' => 0,
                 '_rstring' => '',
                 '_filter_cols' => {},
                 '_tempdir' => undef,
                 '_default_row_pixels' => 20,
                 '_margin_top' => '0.75',
                 '_fh' => undef,
                 '_external_background_links' => [],

            [ Snipped for brevity ]

                 '_default_date_pixels' => 68,
                 '_xls_rowmax' => 1048576,
                 '_col_size_changed' => 0,
                 '_set_rows' => {},
                 '_outline_on' => 1,
                 '_str_total' => \2,
                 '_write_match' => [],
                 '_shape_hash' => {}
               }, 'Excel::Writer::XLSX::Worksheet' );

Excel::Writer::XLSX::Worksheet

Screenshot when everything is working as it should and 'die' is commented out: Spreadsheet img

1

There are 1 best solutions below

0
ikegami On

From the documentation,

The write methods return:

  0 for success.
 -1 for insufficient number of arguments.
 -2 for row or column out of bounds.
 -3 for string too long.

$self->{worksheet}->write returns zero on success. You are literally causing your program to fail when the call succeeds. Change the or to an and.

And stop using $! here. $self->{worksheet}->write is not a system call and doesn't otherwise signal setting $! or errno (the C variable $! proxies). $! is meaningless even on error.