home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam    

Perl CookbookPerl CookbookSearch this book

7.23. Reading an Entire Line Without Blocking

7.23.3. Discussion

As described in Recipe 7.22, to determine whether the operating system has data on a particular handle for your process to read, you can use either Perl's built-in select function or the can_read method from the standard IO::Select module.

Although you can reasonably use functions like sysread and recv to get data, you can't use the buffered functions like readline (that is, <FH>), read, or getc. Also, even the unbuffered input functions might still block. If someone connects and sends a character but never sends a newline, your program will block in a <FH>, which expects its input to end in a newline—or in whatever you've assigned to the $/ variable.

We circumvent this by setting the handle to non-blocking mode and then reading in characters until we find "\n". This removes the need for the blocking <FH> call. The sysreadline function in the Solution takes an optional second argument so you don't have to wait forever in case you get a partial line and nothing more.

A far more serious issue is that select reports only whether the operating system's low-level file descriptor is available for I/O. It's not reliable in the general case to mix calls to four-argument select with calls to any of the buffered I/O functions listed in this chapter's Introduction (read, <FH>, seek, tell, etc.). Instead, you must use sysread—and sysseek if you want to reposition the filehandle within the file.

The reason is that select's response does not reflect any user-level buffering in your own process's address space once the kernel has transferred the data. But the <FH>—really Perl's readline( ) function—still uses your underlying buffered I/O system. If two lines were waiting, select would report true only once. You'd read the first line and leave the second one in the buffer. But the next call to select would block because, as far as the kernel is concerned, it's already given you all of the data it had. That second line, now hidden from your kernel, sits unread in an input buffer that's solely in user space.

Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.