tags:

views:

78

answers:

2

My sysopen fails:

sysopen(DEV, "/dev/ttyS0", O_NONBLOCK|O_RDONLY)

returns 1, which is a success! Then, why does $! have the error "Illegal seek" in it (where it is undef before the call)

before sysopen $!:
after sysopen $!: Illegal seek

EDIT: Here is the full script: (using the actual O_NONBLOCK|O_RDONLY value 2048)

 #!/usr/bin/perl -w
 use Device::SerialPort;
 my $ob;

 $ob = new Device::SerialPort("/dev/ttyS0");

 print $!, "\n";
 $! = 0;

 my $ret = sysopen(DEV, "/dev/ttyS0", 2048);

 print $!, "\n";
 $! = 0;

 print "ret from sysopen: ", $ret, "\n";
 #my $dev = <DEV>;

which prints out: ./filehandle.pl Illegal seek Illegal seek ret from sysopen: 1

+11  A: 

That's how the C errno variable works. To quote from man errno:

Its value is significant only when the return value of the call indicated an error (i.e., -1 from most system calls; -1 or NULL from most library functions); a function that succeeds is allowed to change errno.

$! is just Perl's interface to errno, and has the same behavior:

This means that the value of $! is meaningful only immediately after a failure

You must check the return value of sysopen to determine whether it failed. If it failed, $! will tell you why it failed, but you can't use $! to determine whether it failed (unless the particular function you're using is documented to set $! to 0 on success. Most don't, including sysopen).

cjm
thank you for pointing that out! i was really struggling with it all day
dissectcode
+1  A: 

Many similar special variables in Perl don't change their value until they have to. You always should check for the condition that would actually set the variable. Two of the most common examples are resetting error variables when there is an error or resetting regex capture variables on a successful match.

 unless( sysopen( ... ) ) {
      die "Error was $!";
      }

 if( m/(...)(...)/ ) {
      print "Found $1 and $2\n";
      }

This is certainly one of Perl's warts since it relies on side effects of distant global variables to denote what happened locally. It's even a bit worse in some cases because something else can change the special variable before you get a chance to look at it so you always should inspect it immediately before running any other statements.

brian d foy
That's not really his problem here. It's not that he's checking it too late, and something else changed it. It's that a function that succeeds can still set `$!` to some non-empty value, but that does **not** indicate that the function failed.
cjm
The solution is the same though. Only look at it under the conditions that would set it to an interesting value. It's a general best practice.
brian d foy
I was trying to use it as an error checking method...thank you for the info it helps A LOT. (I edited my orig post with the full script like you wanted)
dissectcode