Better error handling

This commit is contained in:
topjohnwu 2022-04-28 03:32:39 -07:00
parent 3ccd3cd57e
commit 11ed6e8034
4 changed files with 52 additions and 63 deletions

View File

@ -209,7 +209,7 @@ class FileSystemService extends IFileSystemService.Stub {
if (e.errno == OsConstants.EEXIST) {
p.add(null);
} else {
p.add(new IOException(e));
p.add(e);
}
p.add(false);
}
@ -297,7 +297,7 @@ class FileSystemService extends IFileSystemService.Stub {
}
values.add(handle);
} catch (ErrnoException e) {
values.set(0, new IOException(e));
values.set(0, e);
h.close();
}
return values;
@ -354,10 +354,8 @@ class FileSystemService extends IFileSystemService.Stub {
}
}
values.add((int) result);
} catch (IOException e) {
} catch (IOException | ErrnoException e) {
values.set(0, e);
} catch (ErrnoException e) {
values.set(0, new IOException(e));
}
return values;
}
@ -399,10 +397,8 @@ class FileSystemService extends IFileSystemService.Stub {
}
}
}
} catch (IOException e) {
} catch (IOException | ErrnoException e) {
values.set(0, e);
} catch (ErrnoException e) {
values.set(0, new IOException(e));
}
return values;
}
@ -417,10 +413,8 @@ class FileSystemService extends IFileSystemService.Stub {
h.ensureOpen();
values.add(Os.lseek(h.fd, offset, whence));
}
} catch (IOException e) {
} catch (IOException | ErrnoException e) {
values.set(0, e);
} catch (ErrnoException e) {
values.set(0, new IOException(e));
}
return values;
}
@ -438,10 +432,8 @@ class FileSystemService extends IFileSystemService.Stub {
values.add(Os.lseek(h.fd, 0, SEEK_CUR));
Os.lseek(h.fd, cur, SEEK_SET);
}
} catch (IOException e) {
} catch (IOException | ErrnoException e) {
values.set(0, e);
} catch (ErrnoException e) {
values.set(0, new IOException(e));
}
return values;
}
@ -456,10 +448,8 @@ class FileSystemService extends IFileSystemService.Stub {
h.ensureOpen();
Os.ftruncate(h.fd, length);
}
} catch (IOException e) {
} catch (IOException | ErrnoException e) {
values.set(0, e);
} catch (ErrnoException e) {
values.set(0, new IOException(e));
}
return values;
}
@ -477,10 +467,8 @@ class FileSystemService extends IFileSystemService.Stub {
else
Os.fdatasync(h.fd);
}
} catch (IOException e) {
} catch (IOException | ErrnoException e) {
values.set(0, e);
} catch (ErrnoException e) {
values.set(0, new IOException(e));
}
return values;
}

View File

@ -40,6 +40,8 @@ import android.util.MutableLong;
import androidx.annotation.RequiresApi;
import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.OpenOption;
@ -48,6 +50,8 @@ import java.util.Set;
class FileUtils {
private static final String REMOTE_ERR_MSG = "Exception thrown on remote process";
private static Object os;
private static Method splice;
private static Method sendfile;
@ -189,4 +193,32 @@ class FileUtils {
}
}
}
static void checkException(ParcelValues values) throws IOException {
Throwable err = values.getTyped(0);
if (err == null)
return;
if (err instanceof IOException) {
try {
// Wrap the exception with its own class so that the rethrown exception
// has the same type. This wrapping is to make it clear that the exception
// originates from a remote process, not local.
Constructor<?> c = err.getClass().getConstructor(String.class);
IOException e = (IOException) c.newInstance(REMOTE_ERR_MSG);
e.initCause(err);
throw e;
} catch (ReflectiveOperationException e) {
// In theory there should be no exception without a constructor that
// accepts a single string as message. In this case, just rethrow.
throw (IOException) err;
}
} else {
throw new IOException(REMOTE_ERR_MSG, err);
}
}
static <T> T tryAndGet(ParcelValues values) throws IOException {
checkException(values);
return values.getTyped(1);
}
}

View File

@ -66,12 +66,7 @@ class RemoteFile extends FileImpl<RemoteFile> {
@NonNull
public String getCanonicalPath() throws IOException {
try {
ParcelValues b = fs.getCanonicalPath(getPath());
IOException ex = b.getTyped(0);
if (ex != null) {
throw ex;
}
return b.getTyped(1);
return FileUtils.tryAndGet(fs.getCanonicalPath(getPath()));
} catch (RemoteException e) {
throw new IOException(e);
}
@ -198,12 +193,7 @@ class RemoteFile extends FileImpl<RemoteFile> {
@Override
public boolean createNewFile() throws IOException {
try {
ParcelValues b = fs.createNewFile(getPath());
IOException ex = b.getTyped(0);
if (ex != null) {
throw ex;
}
return b.getTyped(1);
return FileUtils.tryAndGet(fs.createNewFile(getPath()));
} catch (RemoteException e) {
throw new IOException(e);
}
@ -212,12 +202,7 @@ class RemoteFile extends FileImpl<RemoteFile> {
@Override
public boolean createNewLink(String existing) throws IOException {
try {
ParcelValues b = fs.createLink(getPath(), existing, false);
IOException ex = b.getTyped(0);
if (ex != null) {
throw ex;
}
return b.getTyped(1);
return FileUtils.tryAndGet(fs.createLink(getPath(), existing, false));
} catch (RemoteException e) {
throw new IOException(e);
}
@ -226,12 +211,7 @@ class RemoteFile extends FileImpl<RemoteFile> {
@Override
public boolean createNewSymlink(String target) throws IOException {
try {
ParcelValues b = fs.createLink(getPath(), target, true);
IOException ex = b.getTyped(0);
if (ex != null) {
throw ex;
}
return b.getTyped(1);
return FileUtils.tryAndGet(fs.createLink(getPath(), target, true));
} catch (RemoteException e) {
throw new IOException(e);
}

View File

@ -65,7 +65,7 @@ class RemoteFileChannel extends FileChannel {
Os.mkfifo(fifo.getPath(), 0644);
// Open the file on the remote process
handle = checkAndGet(fs.open(file.getAbsolutePath(), mode, fifo.getPath()));
handle = FileUtils.tryAndGet(fs.open(file.getAbsolutePath(), mode, fifo.getPath()));
// Since we do not have the machinery to interrupt native pthreads, we
// have to make sure none of our I/O can block in all operations.
@ -79,17 +79,6 @@ class RemoteFileChannel extends FileChannel {
}
}
private static void check(ParcelValues values) throws IOException {
IOException ex = values.getTyped(0);
if (ex != null)
throw ex;
}
private static <T> T checkAndGet(ParcelValues values) throws IOException {
check(values);
return values.getTyped(1);
}
private void ensureOpen() throws IOException {
if (!isOpen())
throw new ClosedChannelException();
@ -127,7 +116,7 @@ class RemoteFileChannel extends FileChannel {
synchronized (fdLock) {
if (!isOpen() || Thread.interrupted())
return -1;
len = checkAndGet(fs.pread(handle, limit - pos, offset));
len = FileUtils.tryAndGet(fs.pread(handle, limit - pos, offset));
if (len == 0)
break;
dst.limit(pos + len);
@ -184,7 +173,7 @@ class RemoteFileChannel extends FileChannel {
if (!isOpen() || Thread.interrupted())
return -1;
len = Os.write(write, src);
check(fs.pwrite(handle, len, offset));
FileUtils.checkException(fs.pwrite(handle, len, offset));
}
if (offset >= 0) {
offset += len;
@ -226,7 +215,7 @@ class RemoteFileChannel extends FileChannel {
public long position() throws IOException {
ensureOpen();
try {
return checkAndGet(fs.lseek(handle, 0, OsConstants.SEEK_CUR));
return FileUtils.tryAndGet(fs.lseek(handle, 0, OsConstants.SEEK_CUR));
} catch (RemoteException e) {
throw new IOException(e);
}
@ -238,7 +227,7 @@ class RemoteFileChannel extends FileChannel {
if (newPosition < 0)
throw new IllegalArgumentException();
try {
check(fs.lseek(handle, newPosition, OsConstants.SEEK_SET));
FileUtils.checkException(fs.lseek(handle, newPosition, OsConstants.SEEK_SET));
return this;
} catch (RemoteException e) {
throw new IOException(e);
@ -249,7 +238,7 @@ class RemoteFileChannel extends FileChannel {
public long size() throws IOException {
ensureOpen();
try {
return checkAndGet(fs.size(handle));
return FileUtils.tryAndGet(fs.size(handle));
} catch (RemoteException e) {
throw new IOException(e);
}
@ -263,7 +252,7 @@ class RemoteFileChannel extends FileChannel {
if (!writable())
throw new NonWritableChannelException();
try {
check(fs.ftruncate(handle, size));
FileUtils.checkException(fs.ftruncate(handle, size));
return this;
} catch (RemoteException e) {
throw new IOException(e);
@ -274,7 +263,7 @@ class RemoteFileChannel extends FileChannel {
public void force(boolean metaData) throws IOException {
ensureOpen();
try {
check(fs.sync(handle, metaData));
FileUtils.checkException(fs.sync(handle, metaData));
} catch (RemoteException e) {
throw new IOException(e);
}