Date: Mon, 21 Jul 2003 12:38:17 +0200 From: Sheldon Hearn <sheldonh@FreeBSD.org> To: freebsd-java@FreeBSD.org Subject: IntelliJ IDEA "Bad file descriptor" [SOLVED] Message-ID: <20030721103817.GG87913@starjuice.net>
next in thread | raw e-mail | index | archive | help
Hi folks, The IntelliJ IDEA IDE for Java has exposed a bug in FreeBSD's native jdk-1.4.1 (ports/java/jdk14). Some excellent support (the norm) from Serge Baranov at IntelliJ got us on the right track, and it wasn't long before Greg Lewis and Alexey Zelkin isolated the problem. The problem exists in the NIO FileChannelImpl implementation on FreeBSD's native jdk-1.4.1. We used Solaris' FileChannelImpl.c as a starting point for our own. The implementation uses the sendfile() system call. Unfortunately sendfile() is a non-standard system call. Solaris and Linux implement file-to-file copy support in sendfile(), while HP-UX and FreeBSD implement only file-to-socket copy support. Thus you should get ENOTSOCK (Socket operation on non-socket). Unfortunately, our FileChannelImpl.c swapped the srcFD and dstFD descriptor arguments to our sendfile() syscall, resulting in EBADF (Bad file descriptor). Greg Lewis asked me to try out the attached patch for FreeBSD's native jdk-1.4.1 (ports/java/jdk14). I've tested it, and it works around the problem nicely. With a patched JDK (and updated ${idea.install.dir}/jre), IDEA no longer exhibits the broken copy behaviour ("Bad file descriptor" caching jars and copying resources). We'll raise the issue on freebsd-arch, in case there's interest in file-to-file sendfile() copy support. If not, the long-term solution here is probably to detect whether dstFD is a socket descriptor and use sendfile() in that case, falling back to pread() and write() otherwise. But for those of you who can't wait, the patch should tide you over. When it's committed to the ports tree, it'll probably take the name ports/java/jdk14/files/patch-FileChannelImpl.c . Big thanks to Greg, Alexey and the ever-helpful Serge Baranov at IntelliJ. Ciao, Sheldon. Index: j2se/src/solaris/native/sun/nio/ch/FileChannelImpl.c =================================================================== RCS file: /var/jcvs/javasrc_1_4_scsl/j2se/src/solaris/native/sun/nio/ch/FileChannelImpl.c,v retrieving revision 1.5 diff -u -r1.5 FileChannelImpl.c --- ../../j2se/src/solaris/native/sun/nio/ch/FileChannelImpl.c 6 Jun 2003 15:31:42 -0000 1.5 +++ ../../j2se/src/solaris/native/sun/nio/ch/FileChannelImpl.c 18 Jul 2003 16:49:33 -0000 @@ -186,15 +186,28 @@ } return n; #elif defined(__FreeBSD__) +#include <errno.h> +#include <stdlib.h> /* * XXXBSD: make sure that we're returning what java class may understand */ + void *buf; off_t offset = (off_t)position; - int n = sendfile(dstFD, srcFD, offset, (size_t)count, NULL, NULL, 0); - if (n < 0) { + int r, w; + + buf = malloc(4096); + while ((r = pread(srcFD, buf, 4096, offset)) > 0) { + w = write(dstFD, buf, r); + if (w == -1) + break; + offset += w; + } + free(buf); + if (r == -1 || w == -1) { + fprintf(stderr, "%d %d %d %d %d\n", srcFD, dstFD, r, w, errno); JNU_ThrowIOExceptionWithLastError(env, "Transfer failed"); } - return n; + return (offset - position); #else return IOS_UNSUPPORTED; #endif
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030721103817.GG87913>