Author: mturk Date: Fri Aug 12 07:07:45 2011 New Revision: 1156987 URL: http://svn.apache.org/viewvc?rev=1156987&view=rev Log: Misc sendfile fixes
Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/Sendfile.java commons/sandbox/runtime/trunk/src/main/native/configure commons/sandbox/runtime/trunk/src/main/native/os/linux/sendfile.c commons/sandbox/runtime/trunk/src/main/native/os/solaris/sendfile.c commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h commons/sandbox/runtime/trunk/src/main/native/os/unix/sendfile.c commons/sandbox/runtime/trunk/src/main/native/os/unix/sockstream.c commons/sandbox/runtime/trunk/src/main/native/os/win32/config.hw commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfile.c commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestServerEndpoint.java Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/Sendfile.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/Sendfile.java?rev=1156987&r1=1156986&r2=1156987&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/Sendfile.java (original) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/net/Sendfile.java Fri Aug 12 07:07:45 2011 @@ -27,6 +27,8 @@ import java.net.SocketException; import org.apache.commons.runtime.io.ClosedDescriptorException; import org.apache.commons.runtime.io.Descriptor; import org.apache.commons.runtime.io.Stream; +import org.apache.commons.runtime.AccessDeniedException; +import org.apache.commons.runtime.NoSuchObjectException; import org.apache.commons.runtime.OperationNotImplementedException; import org.apache.commons.runtime.OverflowException; @@ -54,9 +56,17 @@ public class Sendfile implements Closeab /** * Creates a new Sendfile object. + * + * @throws AccessDeniedException if the access to the file is not allowed. + * @throws NoSuchObjectException if the file doesn't exsist. + * @throws UnsupportedOperationException if the sendfile is not permitted on the given file. + * @throws IOException if an I/O error occurs. */ public Sendfile(String path) - throws IOException + throws AccessDeniedException, + NoSuchObjectException, + UnsupportedOperationException, + IOException { sf = open0(path); closed = false; @@ -64,9 +74,16 @@ public class Sendfile implements Closeab /** * Creates a new Sendfile object. + * + * @throws AccessDeniedException if the access to the file is not allowed. + * @throws NoSuchObjectException if the file doesn't exsist. + * @throws IOException if an I/O error occurs. */ public Sendfile(File path) - throws IOException + throws AccessDeniedException, + NoSuchObjectException, + UnsupportedOperationException, + IOException { sf = open0(path.getPath()); closed = false; @@ -109,13 +126,21 @@ public class Sendfile implements Closeab * The function sends file data and returns the number of bytes * actually send. User should call this function untill it returns * {@code zero}. - * + * <p> + * In case this method throws {@code UnsupportedOperationException} user + * should try to use the traditional method to send the file content. + * </p> * @return number of bytes send or {@code -1} if the * entire file was send. + * + * @throws ClosedDescriptorException if this object or endpoint is closed. + * @throws UnsupportedOperationException if the file or socket does not + * support sendfile operation. * @throws IOException in case of error. */ public int send(Endpoint endpoint) - throws IOException + throws UnsupportedOperationException, + IOException { if (endpoint.closed() || closed) throw new ClosedDescriptorException(); @@ -126,9 +151,11 @@ public class Sendfile implements Closeab * Get the size of the file to send. * * @return number of bytes that equals to opened file size. + * + * @throws ClosedDescriptorException if this object is closed. */ public long length() - throws IOException + throws ClosedDescriptorException { if (closed) throw new ClosedDescriptorException(); @@ -139,9 +166,11 @@ public class Sendfile implements Closeab * Returns the number of bytes send so far. * * @return number of bytes send so far. + * + * @throws ClosedDescriptorException if this object is closed. */ public long position() - throws IOException + throws ClosedDescriptorException { if (closed) throw new ClosedDescriptorException(); @@ -152,9 +181,11 @@ public class Sendfile implements Closeab * Returns the number of bytes to be send. * * @return number of bytes that has to be send. + * + * @throws ClosedDescriptorException if this object is closed. */ public long remaining() - throws IOException + throws ClosedDescriptorException { if (closed) throw new ClosedDescriptorException(); Modified: commons/sandbox/runtime/trunk/src/main/native/configure URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/configure?rev=1156987&r1=1156986&r2=1156987&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/configure (original) +++ commons/sandbox/runtime/trunk/src/main/native/configure Fri Aug 12 07:07:45 2011 @@ -1392,6 +1392,7 @@ extern "C" { #define HAVE_READDIR64_R `have_function x readdir64_r` #define HAVE_MMAP64 `have_function x mmap64` #define HAVE_POSIX_MEMALIGN `have_function x posix_memalign` +#define HAVE_POSIX_FADVISE `have_function x posix_fadvise` #define HAVE_FDATASYNC `have_function x fdatasync` #define HAVE_FLOCK `have_function x flock` #define HAVE_CLOCK_GETTIME `have_function x clock_gettime` Modified: commons/sandbox/runtime/trunk/src/main/native/os/linux/sendfile.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/linux/sendfile.c?rev=1156987&r1=1156986&r2=1156987&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/linux/sendfile.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/linux/sendfile.c Fri Aug 12 07:07:45 2011 @@ -42,24 +42,25 @@ ACR_NET_EXPORT(jint, Sendfile, send0)(JN acr_sf_t *sf = J2P(fp, acr_sf_t *); int sock; int xmitted = 0; - size_t tosend = ZERO_FILE_LINE_CHUNK; + ssize_t tosend; if ((sock = AcrSdRetain(sd)) == -1) { ACR_THROW_NET_ERROR(ACR_EBADF); - return -1; - } - if (sf->size != 0) { - if ((sf->size - sf->off) > INT_MAX) - tosend = INT_MAX; - else - tosend = (size_t)(sf->size - sf->off); + return 0; } + if ((sf->size - sf->off) > INT_MAX) + tosend = INT_MAX; + else + tosend = (ssize_t)(sf->size - sf->off); if (ACR_HASFLAG(sd, ACR_SO_WPART)) { /* Flush any previous writes */ ACR_CLRFLAG(sd, ACR_SO_WPART); rc = AcrWaitIO(sock, sd->timeout, POLLOUT); - if (rc != 0) - goto finally; + if (rc != 0) { + AcrSdRelease(sd); + ACR_THROW_NET_ERROR(rc); + return 0; + } } if (tosend == 0) { AcrSdRelease(sd); @@ -67,7 +68,6 @@ ACR_NET_EXPORT(jint, Sendfile, send0)(JN } while (tosend > 0) { ssize_t wr; - off_t offset = sf->off; do { wr = sendfile(sock, /* socket */ sf->fd, /* file descriptor of the file to be sent */ @@ -77,24 +77,25 @@ ACR_NET_EXPORT(jint, Sendfile, send0)(JN if (wr == -1) { rc = errno; - if ((rc == EAGAIN || rc == EWOULDBLOCK) && sd->timeout > 0) { - if ((rc = AcrWaitIO(sock, sd->timeout, POLLOUT)) == 0) { - /* We have send someting. - * See how many bytes was actually send. - */ - wr = (ssize_t)(sf->off - offset); - } + if (ACR_STATUS_IS_EAGAIN(rc) && sd->timeout > 0) { + wr = 0; + rc = AcrWaitIO(sock, sd->timeout, POLLOUT); } + else if (rc == EINVAL) + rc = ENOSYS; } if (rc != 0) break; tosend -= wr; xmitted += wr; } -finally: - if (rc != 0 && xmitted == 0) { - xmitted = -1; + if (rc != 0 && xmitted == 0) ACR_THROW_NET_ERROR(rc); + else if (sd->timeout > 0 && tosend > 0) { + /* Partial write. + * The next write call will have to wait for IO event. + */ + ACR_SETFLAG(sd, ACR_SO_WPART); } AcrSdRelease(sd); return xmitted; Modified: commons/sandbox/runtime/trunk/src/main/native/os/solaris/sendfile.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/solaris/sendfile.c?rev=1156987&r1=1156986&r2=1156987&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/solaris/sendfile.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/solaris/sendfile.c Fri Aug 12 07:07:45 2011 @@ -33,33 +33,33 @@ * Used for files that report st_size == 0 * like /proc/ file system */ -#define ZERO_FILE_LINE_CHUNK 4096 - ACR_NET_EXPORT(jint, Sendfile, send0)(JNI_STDARGS, jlong sp, jlong fp) { int rc = 0; acr_sd_t *sd = J2P(sp, acr_sd_t *); acr_sf_t *sf = J2P(fp, acr_sf_t *); + int once = 1; int sock; int xmitted = 0; - size_t tosend = ZERO_FILE_LINE_CHUNK; + ssize_t tosend; if ((sock = AcrSdRetain(sd)) == -1) { ACR_THROW_NET_ERROR(ACR_EBADF); - return -1; - } - if (sf->size != 0) { - if ((sf->size - sf->off) > INT_MAX) - tosend = INT_MAX; - else - tosend = (size_t)(sf->size - sf->off); + return 0; } + if ((sf->size - sf->off) > INT_MAX) + tosend = INT_MAX; + else + tosend = (ssize_t)(sf->size - sf->off); if (ACR_HASFLAG(sd, ACR_SO_WPART)) { /* Flush any previous writes */ ACR_CLRFLAG(sd, ACR_SO_WPART); rc = AcrWaitIO(sock, sd->timeout, POLLOUT); - if (rc != 0) - goto finally; + if (rc != 0) { + AcrSdRelease(sd); + ACR_THROW_NET_ERROR(rc); + return 0; + } } if (tosend == 0) { AcrSdRelease(sd); @@ -77,24 +77,34 @@ ACR_NET_EXPORT(jint, Sendfile, send0)(JN if (wr == -1) { rc = errno; - if ((rc == EAGAIN || rc == EWOULDBLOCK) && sd->timeout > 0) { - if ((rc = AcrWaitIO(sock, sd->timeout, POLLOUT)) == 0) { - /* We have send someting. - * See how many bytes was actually send. - */ - wr = (ssize_t)(sf->off - offset); + if (rc == EAGAIN) { + wr = (ssize_t)(sf->off - offset); + if (wr != 0) { + /* Solaris can return -1/EAGAIN even if + * data was send on non-blocking socket. + */ + rc = 0; + } + else if (once && sd->timeout > 0) { + rc = AcrWaitIO(sock, sd->timeout, POLLOUT); + once = 0; } } + else if (rc == EAFNOSUPPORT || rc == EOPNOTSUPP) + rc = ENOSYS; } if (rc != 0) break; tosend -= wr; xmitted += wr; } -finally: - if (rc != 0 && xmitted == 0) { - xmitted = -1; + if (rc != 0 && xmitted == 0) ACR_THROW_NET_ERROR(rc); + else if (sd->timeout > 0 && tosend > 0) { + /* Partial write. + * The next write call will have to wait for IO event. + */ + ACR_SETFLAG(sd, ACR_SO_WPART); } AcrSdRelease(sd); return xmitted; Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h?rev=1156987&r1=1156986&r2=1156987&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/unix/arch_opts.h Fri Aug 12 07:07:45 2011 @@ -87,6 +87,17 @@ ACR_INLINE(ssize_t) r_write(int fd, cons return w; } +/* restartable writev() */ +ACR_INLINE(ssize_t) r_writev(int fd, const struct iovec *iov, int iovcnt) +{ + ssize_t w; + do { + w = writev(fd, iov, iovcnt); + } while (w == -1 && errno == EINTR); + + return w; +} + /* restartable pread() */ ACR_INLINE(ssize_t) r_pread(int fd, void *buf, size_t count, off_t offset) { Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/sendfile.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/sendfile.c?rev=1156987&r1=1156986&r2=1156987&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/unix/sendfile.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/unix/sendfile.c Fri Aug 12 07:07:45 2011 @@ -37,12 +37,12 @@ ACR_NET_EXPORT(jlong, Sendfile, open0)(J sf->fd = -1; WITH_CSTR(fname) { int flags = O_RDONLY; -#ifdef O_LARGEFILE - flags |= O_LARGEFILE; -#endif #ifdef O_CLOEXEC flags |= O_CLOEXEC; #endif +#ifdef O_NOATIME + flags |= O_NOATIME; +#endif sf->fd = open(J2S(fname), flags); if (sf->fd != -1) { #ifndef O_CLOEXEC @@ -55,6 +55,18 @@ ACR_NET_EXPORT(jlong, Sendfile, open0)(J sf->size = info.st_size; } } +#if HAVE_POSIX_FADVISE + if (posix_fadvise(sf->fd, 0, 0, POSIX_FADV_SEQUENTIAL) == -1) { +#if defined(DEBUG) || defined(_DEBUG) + if (errno != ENOSYS) + rc = errno; +#endif + } +#endif + /* Check if we opened supported file type */ + if (S_ISDIR(info.st_mode) || S_ISFIFO(info.st_mode) || + S_ISSOCK(info.st_mode)) + rc = ENOSYS; } DONE_WITH_STR(fname); if (rc != 0) { s_close(sf->fd); Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/sockstream.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/sockstream.c?rev=1156987&r1=1156986&r2=1156987&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/unix/sockstream.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/unix/sockstream.c Fri Aug 12 07:07:45 2011 @@ -161,8 +161,7 @@ ACR_NET_EXPORT(jint, SocketStream, read0 if (ACR_HASFLAG(ss->fd, ACR_SO_RDEOF)) goto finally; rd = r_read(sd, &ch, 1); - if (rd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && - ss->fd->timeout > 0) { + if (rd == -1 && ACR_STATUS_IS_EAGAIN(errno) && ss->fd->timeout > 0) { rc = AcrWaitIO(sd, ss->fd->timeout, POLLIN); if (rc != 0) goto finally; @@ -225,8 +224,7 @@ ACR_NET_EXPORT(jint, SocketStream, read1 goto waitio; } rd = r_read(sd, bb, len); - if (rd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && - ss->fd->timeout > 0) { + if (rd == -1 && ACR_STATUS_IS_EAGAIN(errno) && ss->fd->timeout > 0) { waitio: rc = AcrWaitIO(sd, ss->fd->timeout, POLLIN); if (rc != 0) @@ -292,8 +290,7 @@ ACR_NET_EXPORT(jint, SocketStream, read2 goto waitio; } rd = r_read(sd, bb + po, len); - if (rd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && - ss->fd->timeout > 0) { + if (rd == -1 && ACR_STATUS_IS_EAGAIN(errno) && ss->fd->timeout > 0) { waitio: rc = AcrWaitIO(sd, ss->fd->timeout, POLLIN); if (rc != 0) @@ -344,8 +341,7 @@ ACR_NET_EXPORT(jint, SocketStream, read3 goto waitio; } rd = r_read(sd, bb + off, len); - if (rd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && - ss->fd->timeout > 0) { + if (rd == -1 && ACR_STATUS_IS_EAGAIN(errno) && ss->fd->timeout > 0) { waitio: rc = AcrWaitIO(sd, ss->fd->timeout, POLLIN); if (rc != 0) @@ -387,8 +383,7 @@ ACR_NET_EXPORT(jint, SocketStream, write goto waitio; } wr = r_write(sd, &ch, 1); - if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && - ss->fd->timeout > 0) { + if (wr == -1 && ACR_STATUS_IS_EAGAIN(errno) && ss->fd->timeout > 0) { waitio: rc = AcrWaitIO(sd, ss->fd->timeout, POLLOUT); if (rc != 0) @@ -433,8 +428,7 @@ ACR_NET_EXPORT(jint, SocketStream, write goto waitio; } wr = r_write(sd, bb + off, len); - if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && - ss->fd->timeout > 0) { + if (wr == -1 && ACR_STATUS_IS_EAGAIN(errno) && ss->fd->timeout > 0) { waitio: rc = AcrWaitIO(sd, ss->fd->timeout, POLLOUT); if (rc != 0) @@ -481,8 +475,7 @@ ACR_NET_EXPORT(jint, SocketStream, write goto waitio; } wr = r_write(sd, bb + po, len); - if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && - ss->fd->timeout > 0) { + if (wr == -1 && ACR_STATUS_IS_EAGAIN(errno) && ss->fd->timeout > 0) { waitio: rc = AcrWaitIO(sd, ss->fd->timeout, POLLOUT); if (rc != 0) @@ -527,8 +520,7 @@ ACR_NET_EXPORT(jint, SocketStream, write goto waitio; } wr = r_write(sd, bb + off, len); - if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && - ss->fd->timeout > 0) { + if (wr == -1 && ACR_STATUS_IS_EAGAIN(errno) && ss->fd->timeout > 0) { waitio: rc = AcrWaitIO(sd, ss->fd->timeout, POLLOUT); if (rc != 0) @@ -604,19 +596,13 @@ ACR_NET_EXPORT(jlong, SocketStream, writ ACR_CLRFLAG(ss->fd, ACR_SO_WPART); goto waitio; } - do { - wr = writev(sd, iov, len); - } while (wr == -1 && errno == EAGAIN); - - if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && - ss->fd->timeout > 0) { + wr = r_writev(sd, iov, len); + if (wr == -1 && ACR_STATUS_IS_EAGAIN(errno) && ss->fd->timeout > 0) { waitio: rc = AcrWaitIO(sd, ss->fd->timeout, POLLOUT); if (rc != 0) goto finally; - do { - wr = writev(sd, iov, len); - } while (wr == -1 && errno == EAGAIN); + wr = r_writev(sd, iov, len); } if (wr == -1) rc = ACR_GET_NETOS_ERROR(); @@ -688,19 +674,14 @@ ACR_NET_EXPORT(jlong, SocketStream, writ ACR_CLRFLAG(ss->fd, ACR_SO_WPART); goto waitio; } - do { - wr = writev(sd, iov, len); - } while (wr == -1 && errno == EAGAIN); - if (wr == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && - ss->fd->timeout > 0) { + wr = r_writev(sd, iov, len); + if (wr == -1 && ACR_STATUS_IS_EAGAIN(errno) && ss->fd->timeout > 0) { waitio: rc = AcrWaitIO(sd, ss->fd->timeout, POLLOUT); if (rc != 0) goto finally; - do { - wr = writev(sd, iov, len); - } while (wr == -1 && errno == EAGAIN); + wr = r_writev(sd, iov, len); } if (wr == -1) rc = ACR_GET_NETOS_ERROR(); Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/config.hw URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/config.hw?rev=1156987&r1=1156986&r2=1156987&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/config.hw (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/config.hw Fri Aug 12 07:07:45 2011 @@ -66,7 +66,7 @@ #define HAVE_READDIR64_R 0 #define HAVE_MMAP64 0 #define HAVE_POSIX_MEMALIGN 0 -#define HAVE_POSIX_SEMAPHORE 0 +#define HAVE_POSIX_FADVISE 0 #define HAVE_FDATASYNC 0 #define HAVE_FLOCK 0 #define HAVE_CLOCK_GETTIME 0 @@ -142,6 +142,7 @@ #define HAVE_FUNCTION 1 #define HAVE_FUNC 0 #define HAVE_FUNCSIG 1 +#define HAVE_POSIX_SEMAPHORE 0 #define HAVE_THREAD_LOCAL 1 #define HAVE_SO_RCVTIMEO 1 #define HAVE_SO_SNDTIMEO 1 Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfile.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfile.c?rev=1156987&r1=1156986&r2=1156987&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfile.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/sendfile.c Fri Aug 12 07:07:45 2011 @@ -46,8 +46,13 @@ ACR_NET_EXPORT(jlong, Sendfile, open0)(J } else { BY_HANDLE_FILE_INFORMATION fi; - if (GetFileInformationByHandle(sf->fh, &fi)) - sf->size = AcrToInt64(fi.nFileSizeHigh, fi.nFileSizeLow); + if (GetFileInformationByHandle(sf->fh, &fi)) { + /* Check if this is a real file */ + if (GetFileType(sf->fh) != FILE_TYPE_DISK) + rc = ACR_ENOSYS; + else + sf->size = AcrToInt64(fi.nFileSizeHigh, fi.nFileSizeLow); + } else rc = GetLastError(); } @@ -157,6 +162,13 @@ ACR_NET_EXPORT(jint, Sendfile, send0)(JN else rc = GetLastError(); } + else if (rc == WSAEINVAL) { + /* Since we manage offsets this can only mean that + * the socket type is not supported in which case + * we should throw UnsupportedOperationException. + */ + rc = ACR_ENOSYS; + } } if (rc != 0) break; Modified: commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestServerEndpoint.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestServerEndpoint.java?rev=1156987&r1=1156986&r2=1156987&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestServerEndpoint.java (original) +++ commons/sandbox/runtime/trunk/src/main/test/org/apache/commons/runtime/TestServerEndpoint.java Fri Aug 12 07:07:45 2011 @@ -145,13 +145,15 @@ public class TestServerEndpoint extends fs.close(); try { Sendfile sf = new Sendfile(sendf); - cs.configureBlocking(false); + cs.setTimeout(200); + assertFalse(cs.isBlocking()); int send = sf.send(cs); assertTrue(send > 0); assertEquals(sf.length() - send, sf.remaining()); cs.configureBlocking(true); System.out.println("Send " + send + " bytes."); } catch (Exception se) { + System.out.println(); System.out.println("Error sending file " + se); } cs.close();