harmony-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Mark Hindess" <mark.hind...@googlemail.com>
Subject Common hyfile_write bug
Date Fri, 30 Apr 2010 21:14:30 GMT

The documentation for hyfile_write says:

 * @return Number of bytes written on success,  -1 on failure.
 * @internal @todo return negative portable return code on failure.

However, the '@todo' is actually done as both the unix and windows
implementations return the result of portLibrary->error_set_last_error(...)
which is the negative portable return code.

Unfortunately, much of the native code depends on the -1 return.  For
instance, OSFileSystem.writeImpl has:

  jlong result;

  result =
    (jlong) hyfile_write ((IDATA) fd, (void *) (bytes + offset),
                         (IDATA) nbytes);
  if(result == -1 &&
     hyerror_last_error_number() == HYPORT_ERROR_FILE_LOCKED){
    throwNewExceptionByName(env, "java/io/IOException", ...);

but in the HYPORT_ERROR_FILE_LOCKED error case 'result' is not -1
but the negative portable return code, HYPORT_ERROR_FILE_LOCKED.  So
this code is never executed.

Test that cover this have been passing because the result is returned
and checked by java code and a generic exception (without the correct
error message) is thrown instead.

There are several issues to notice here:

1) hyfile_write documentation needs fixing.

2) The -1 checks need reviewing and fixing.

3) The -1 check in this case could be removed *but* it would be better
to replace them with:

   if (result < 0) {
     throwNewExceptionByName(env, "java/io/IOException",
                             netLookupErrorString(env, result);

so an accurate exception can be thrown (in all cases not just the file
locked case) and remove the wrapping/exception throwing from java code.
(I nearly always prefer this approach - throwing specific exceptions
in natives - but the use of return codes and generic exceptions is
unfortunately rather prevalent.)

4) The jlong 'result' is representing the return code from a portlibrary
call so really it should have a portlibrary type, IDATA in this case.
It should be cast to a java type in the return statement - that is, at
the boundary where we "move" from native to java code.  This also seems
quite prevalent (particularly using java types for return values of
syscalls rather than the type described in the documentation for the
syscall).  The result is excessive casting of results of calls when
really casting to java types should only happen when making JNI calls or
on return statements.  This also makes the code rather hard to review
since you have to look up the correct return type for the syscall to
ensure that the cast is valid.


View raw message