java.io.IOException bug SOLVED!

Jake Hamby jehamby at lightside.com
Fri Jul 17 18:59:26 PDT 1998


On Fri, 17 Jul 1998, Ren-song Ko wrote:

> I encounter an error 
> 
> error: java.io.IOException: read error
> Illegal Instruction
> 
> while execute "javac HelloWorldApp.java". Could someone help me with
> this? I install Kaffe 1.0.b1 on Sun solaris.

Okay, I figured out the cause of this bug.  In the native methods for
FileInputStream, the available() method uses the FIONREAD ioctl() to
figure out the number of bytes available to read.  Apparently this works
in at least BSD and Linux, but not in Solaris (and maybe other SVR4's?).
The solution is to use fstat() to check if the file descriptor is a
regular file, and if so, use lseek() to determine how many bytes are
remaining, otherwise use FIONREAD (or select()) as before.  This works in
any POSIX OS, and so I think this patch should be applied to the main
kaffe source, just to be safe.  You can verify the correct behavior with
this simple test program:

import java.io.*;
class availtest {
    public static void main(String args[]) {
        try {
          FileInputStream f = new FileInputStream("availtest.java");
          System.out.println("avail: " + f.available());
          f = new FileInputStream(FileDescriptor.in);
          System.out.println("stdin: " + f.available());
        } catch(Exception e) {
            System.err.println(e);
        }
    }
}

On my system, I get:
% kaffe availtest
avail: 361
stdin: 0
% kaffe availtest < availtest.java
avail: 361
stdin: 361

You may get slightly different results depending on how big availtest.java
is on your machine, but of course it should match the 'ls -l' size.

Anyway, here's the patch.  I'm still having problems with the Bean,
ReflectInvoke, and GCTest regression tests, but the others work now.
Enjoy!
-Jake

*** libraries/clib/native/FileInputStream.c.orig	Fri Jul 17 18:33:54 1998
--- libraries/clib/native/FileInputStream.c	Fri Jul 17 18:41:11 1998
***************
*** 124,132 ****
  {
  	int nr;
  	int r;
  
  #if defined(HAVE_IOCTL) && defined(FIONREAD)
! 	r = ioctl(unhand(unhand(fh)->fd)->fd, FIONREAD, &nr);
  	if (r < 0) {
  		nr = 0;
  	}
--- 124,150 ----
  {
  	int nr;
  	int r;
+ 	int fd = unhand(unhand(fh)->fd)->fd;
+ 	struct stat buf;
+ 	
+ 	if(fstat(fd, &buf))
+ 	  return 0;   /* Error stat'ing file */
+ 	
+ 	/* 
+ 	 * We can always get the remaining bytes in a regular file.
+ 	 */
+ 	if(buf.st_mode & S_IFREG) {
+ 	  int cur = lseek(fd, 0, SEEK_SET);
+ 	  nr = lseek(fd, 0, SEEK_END);
+ 	  lseek(fd, cur, SEEK_SET);
+ 	  return nr;
+ 	}
  
+ 	/*
+ 	 * Otherwise we must be dealing with a tty, so use FIONREAD or select()
+ 	 */
  #if defined(HAVE_IOCTL) && defined(FIONREAD)
! 	r = ioctl(fd, FIONREAD, &nr);
  	if (r < 0) {
  		nr = 0;
  	}
***************
*** 135,144 ****
  	 * happens at the end of file?
  	 */
  	static struct timeval tm = { 0, 0 };
- 	int fd;
  	fd_set rd;
  
- 	fd = unhand(unhand(fh)->fd)->fd;
  	FD_ZERO(&rd);
  	FD_SET(fd, &rd);
  	r = select(fd+1, &rd, NULL, NULL, &tm);
--- 153,160 ----





More information about the kaffe mailing list