Skip to content

Commit

Permalink
Run prepare() for BackupSoSource to cleanup previous state
Browse files Browse the repository at this point in the history
Summary:
Currently, the BackupSoSource does not clean after itself when a new version of the app is installed. That is because prepare() does not run unless there is a crash.

This diff changes that by running prepare() with special flags whenever initialising SoLoader. With the new flag, we make sure that `deleteSoFiles` runs when necessary, e.g. when deps have changed.

To differentiate between different states, we simply skip writing sos to disk and the deps state (which is empty).

Reviewed By: danjin250

Differential Revision: D60186847

fbshipit-source-id: e029b9c31ac9a677cae5e9c9d80cf8aee79da35d
  • Loading branch information
adicatana authored and facebook-github-bot committed Jul 31, 2024
1 parent fd35038 commit a5ebc83
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 14 deletions.
3 changes: 2 additions & 1 deletion java/com/facebook/soloader/BackupSoSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ public int loadLibrary(String soName, int loadFlags, StrictMode.ThreadPolicy thr

@Override
public void prepare(int flags) throws IOException {
if ((flags & SoSource.PREPARE_FLAG_SKIP_BACKUP_SO_SOURCE) != 0) {
if ((flags & SoSource.PREPARE_FLAG_NO_UNPACKING_BACKUP_SO_SOURCE) != 0) {
super.prepare(flags | SoSource.PREPARE_FLAG_NO_UNPACKING);
return;
}
super.prepare(flags);
Expand Down
2 changes: 1 addition & 1 deletion java/com/facebook/soloader/SoLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ private static int makePrepareFlags() {
prepareFlags |= SoSource.PREPARE_FLAG_DISABLE_FS_SYNC_JOB;
}
if ((sFlags & SOLOADER_EXPLICITLY_ENABLE_BACKUP_SOSOURCE) == 0) {
prepareFlags |= SoSource.PREPARE_FLAG_SKIP_BACKUP_SO_SOURCE;
prepareFlags |= SoSource.PREPARE_FLAG_NO_UNPACKING_BACKUP_SO_SOURCE;
}
return prepareFlags;
} finally {
Expand Down
4 changes: 3 additions & 1 deletion java/com/facebook/soloader/SoSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ public abstract class SoSource {
public static final int PREPARE_FLAG_DISABLE_FS_SYNC_JOB = (1 << 2);

/** Skip preparing backup so source. */
public static final int PREPARE_FLAG_SKIP_BACKUP_SO_SOURCE = (1 << 3);
public static final int PREPARE_FLAG_NO_UNPACKING_BACKUP_SO_SOURCE = (1 << 3);

public static final int PREPARE_FLAG_NO_UNPACKING = (1 << 4);

/** Prepare to install this SoSource in SoLoader. */
protected void prepare(int flags) throws IOException {
Expand Down
27 changes: 16 additions & 11 deletions java/com/facebook/soloader/UnpackingSoSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -338,18 +338,23 @@ private boolean refreshLocked(final FileLocker lock, final int flags) throws IOE
LogUtil.v(TAG, "so store dirty: regenerating");
writeState(stateFileName, STATE_DIRTY, runFsync);
deleteSoFiles();
try (Unpacker u = makeUnpacker()) {
u.unpack(soDirectory);
}

// N.B. We can afford to write the deps file without fsyncs because we've marked the DSO
// store STATE_DIRTY, which will cause us to ignore all intermediate state when regenerating it.
// That is, it's okay for the depsFile blocks to hit the disk before the actual DSO data file
// blocks as long as both hit the disk before we reset STATE_CLEAN.
final File depsFileName = new File(soDirectory, DEPS_FILE_NAME);
try (RandomAccessFile depsFile = new RandomAccessFile(depsFileName, "rw")) {
depsFile.write(recomputedDeps);
depsFile.setLength(depsFile.getFilePointer());
final boolean noUnpacking = (flags & PREPARE_FLAG_NO_UNPACKING) != 0;
if (!noUnpacking) {
try (Unpacker u = makeUnpacker()) {
u.unpack(soDirectory);
}

// N.B. We can afford to write the deps file without fsyncs because we've marked the DSO
// store STATE_DIRTY, which will cause us to ignore all intermediate state when regenerating
// it.
// That is, it's okay for the depsFile blocks to hit the disk before the actual DSO data file
// blocks as long as both hit the disk before we reset STATE_CLEAN.
final File depsFileName = new File(soDirectory, DEPS_FILE_NAME);
try (RandomAccessFile depsFile = new RandomAccessFile(depsFileName, "rw")) {
depsFile.write(recomputedDeps);
depsFile.setLength(depsFile.getFilePointer());
}
}

// Task to dump the buffer cache to disk to guard against battery outages. The default is to run
Expand Down

0 comments on commit a5ebc83

Please sign in to comment.