Skip to content

Commit

Permalink
Recover DSO not found error for BackupSoSource
Browse files Browse the repository at this point in the history
Summary:
This stack aims to recover the work from an old diff D50323349.

As a first step, we only recover DSO error for BackupSoSource and we only reunpack reunpack if the missing library can be found inside the APK.

Reviewed By: adicatana

Differential Revision: D55876275

fbshipit-source-id: dee52793805f4886dccd060734d995be88ee023d
  • Loading branch information
Rory Shu authored and facebook-github-bot committed Apr 11, 2024
1 parent 995bf5a commit 0fc08d3
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 12 deletions.
21 changes: 21 additions & 0 deletions java/com/facebook/soloader/BackupSoSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,28 @@ public void prepare(int flags) throws IOException {
mInitialized = true;
}

public boolean peekAndPrepareSoSource(String soName, int prepareFlags) throws IOException {
boolean found = false;
try (Unpacker u = makeUnpacker()) {
Dso[] dsos = u.getDsos();
for (Dso dso : dsos) {
if (dso.name.equals(soName)) {
LogUtil.e(SoLoader.TAG, "Found " + soName + " in " + getName());
found = true;
break;
}
}
}
if (!found) {
return false;
}
LogUtil.e(SoLoader.TAG, "Preparing " + getName());
prepare(prepareFlags);
return true;
}

protected class ApkUnpacker extends Unpacker {

@Override
public Dso[] getDsos() throws IOException {
ArrayList<Dso> dsos = new ArrayList<>();
Expand Down
58 changes: 46 additions & 12 deletions java/com/facebook/soloader/recovery/ReunpackBackupSoSources.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.facebook.soloader.SoLoaderDSONotFoundError;
import com.facebook.soloader.SoLoaderULError;
import com.facebook.soloader.SoSource;
import java.io.IOException;

/**
* RecoveryStrategy that detects cases when SoLoader failed to load a corrupted library, case in
Expand All @@ -38,26 +39,50 @@ public boolean recover(UnsatisfiedLinkError error, SoSource[] soSources) {
// Only recover from SoLoaderULE errors
return false;
}
SoLoaderULError err = (SoLoaderULError) error;
String soName = err.getSoName();
String message = err.getMessage();

if (error instanceof SoLoaderDSONotFoundError) {
// Do not attempt to recover if DSO is not found
if (soName == null) {
LogUtil.e(SoLoader.TAG, "No so name provided in ULE, cannot recover");
return false;
}

SoLoaderULError err = (SoLoaderULError) error;
String message = err.getMessage();
if (message == null || (!message.contains("/app/") && !message.contains("/mnt/"))) {
// Do not attempt to recovery if the DSO wasn't in the data/app directory
if (err instanceof SoLoaderDSONotFoundError) {
// Recover if DSO is not found
logRecovery(err, soName);

return recoverDSONotFoundError(soSources, soName, 0);
} else if (message == null || (!message.contains("/app/") && !message.contains("/mnt/"))) {
// Don't recover if the DSO wasn't in the data/app directory

return false;
} else {
logRecovery(err, soName);
return lazyPrepareBackupSoSource(soSources, soName);
}
}

String soName = err.getSoName();
LogUtil.e(
SoLoader.TAG,
"Reunpacking BackupSoSources due to "
+ error
+ ((soName == null) ? "" : (", retrying for specific library " + soName)));
private boolean recoverDSONotFoundError(SoSource[] soSources, String soName, int prepareFlags) {
try {
for (SoSource soSource : soSources) {
if (!(soSource instanceof BackupSoSource)) {
continue;
}
BackupSoSource uss = (BackupSoSource) soSource;

if (uss.peekAndPrepareSoSource(soName, prepareFlags)) {
return true;
}
}
return false;
} catch (IOException ioException) {
LogUtil.e(SoLoader.TAG, "Failed to run recovery for backup so source due to: " + ioException);
return false;
}
}

private boolean lazyPrepareBackupSoSource(SoSource[] soSources, String soName) {
for (SoSource soSource : soSources) {
if (!(soSource instanceof BackupSoSource)) {
// NonApk SoSources get reunpacked in ReunpackNonBackupSoSource recovery strategy
Expand Down Expand Up @@ -88,4 +113,13 @@ public boolean recover(UnsatisfiedLinkError error, SoSource[] soSources) {

return false;
}

private void logRecovery(Error error, String soName) {
LogUtil.e(
SoLoader.TAG,
"Reunpacking BackupSoSources due to "
+ error
+ ", retrying for specific library "
+ soName);
}
}

0 comments on commit 0fc08d3

Please sign in to comment.