mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-20 19:18:37 +00:00
Prevent potential deadlock when canceling jobs.
This commit is contained in:
committed by
Jeffrey Starke
parent
6f051ce4c2
commit
2b56e00e89
@@ -206,7 +206,11 @@ class JobController {
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
synchronized void cancelJob(@NonNull String id) {
|
||||
void cancelJob(@NonNull String id) {
|
||||
Job inactiveJob = null;
|
||||
List<Job> inactiveJobDependents = Collections.emptyList();
|
||||
|
||||
synchronized (this) {
|
||||
Job runningJob = runningJobs.get(id);
|
||||
|
||||
if (runningJob != null) {
|
||||
@@ -216,23 +220,33 @@ class JobController {
|
||||
JobSpec jobSpec = jobStorage.getJobSpec(id);
|
||||
|
||||
if (jobSpec != null) {
|
||||
Job job = createJob(jobSpec, jobStorage.getConstraintSpecs(id));
|
||||
Log.w(TAG, JobLogger.format(job, "Canceling while inactive."));
|
||||
Log.w(TAG, JobLogger.format(job, "Job failed."));
|
||||
inactiveJob = createJob(jobSpec, jobStorage.getConstraintSpecs(id));
|
||||
Log.w(TAG, JobLogger.format(inactiveJob, "Canceling while inactive."));
|
||||
Log.w(TAG, JobLogger.format(inactiveJob, "Job failed."));
|
||||
|
||||
job.cancel();
|
||||
List<Job> dependents = onFailure(job);
|
||||
job.onFailure();
|
||||
Stream.of(dependents).forEach(Job::onFailure);
|
||||
inactiveJob.cancel();
|
||||
inactiveJobDependents = onFailure(inactiveJob);
|
||||
} else {
|
||||
Log.w(TAG, "Tried to cancel JOB::" + id + ", but it could not be found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We have no control over what happens in jobs' onFailure method, so we drop our lock to reduce the possibility of a deadlock
|
||||
if (inactiveJob != null) {
|
||||
inactiveJob.onFailure();
|
||||
Stream.of(inactiveJobDependents).forEach(Job::onFailure);
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
synchronized void cancelAllInQueue(@NonNull String queue) {
|
||||
Stream.of(jobStorage.getJobsInQueue(queue))
|
||||
void cancelAllInQueue(@NonNull String queue) {
|
||||
List<JobSpec> jobsInQueue;
|
||||
synchronized (this) {
|
||||
jobsInQueue = jobStorage.getJobsInQueue(queue);
|
||||
}
|
||||
|
||||
Stream.of(jobsInQueue)
|
||||
.map(JobSpec::getId)
|
||||
.forEach(this::cancelJob);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user