From b4f0b14499b22e5902f04b38a45789fc36f0bceb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Oct 2025 09:19:56 +0000 Subject: [PATCH 1/3] Initial plan From 6cf8ec56de8cd6506b122a3e9651b7984ea27b83 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Oct 2025 09:28:01 +0000 Subject: [PATCH 2/3] Fix Job.schedule() not rescheduling after cancel() The aboutToRunCanceled flag was not being cleared when reschedule=true, causing jobs to be canceled instead of scheduled. This fix moves the flag clearing to after the early returns, ensuring it's always cleared when actually scheduling the job. Fixes eclipse-platform/eclipse.platform#160 Co-authored-by: laeubi <1331477+laeubi@users.noreply.github.com> --- .../src/org/eclipse/core/internal/jobs/JobManager.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/runtime/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java b/runtime/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java index ef4005f7069..88e2a2d5ac5 100644 --- a/runtime/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java +++ b/runtime/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java @@ -1486,9 +1486,6 @@ protected boolean scheduleInternal(InternalJob job, long delay, boolean reschedu } Assert.isNotNull(job, "Job is null"); //$NON-NLS-1$ Assert.isLegal(delay >= 0, "Scheduling delay is negative"); //$NON-NLS-1$ - if (!reschedule) { - job.setAboutToRunCanceled(false); - } // if the job is already running, set it to be rescheduled when done if (job.getState() == Job.RUNNING) { job.setStartTime(delay); // XXX delay used as time @@ -1498,6 +1495,10 @@ protected boolean scheduleInternal(InternalJob job, long delay, boolean reschedu if (job.internalGetState() != Job.NONE) { return false; } + // Clear the about to run canceled flag when actually scheduling. + // A new explicit schedule() call should override any previous cancel() call. + // See https://github.com/eclipse-platform/eclipse.platform/issues/160 + job.setAboutToRunCanceled(false); if (JobManager.DEBUG) { JobManager.debug("Scheduling job: " + job); //$NON-NLS-1$ } From 6df0f1d80cb57df8284406972bc277b4c5426a60 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Oct 2025 09:29:30 +0000 Subject: [PATCH 3/3] Add regression test for issue #160 Test verifies that Job.schedule() works correctly after cancel() when called on a running job. This reproduces the issue where the aboutToRunCanceled flag was not being cleared during reschedule. Co-authored-by: laeubi <1331477+laeubi@users.noreply.github.com> --- .../core/tests/runtime/jobs/Bug_550738.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/runtime/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/runtime/jobs/Bug_550738.java b/runtime/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/runtime/jobs/Bug_550738.java index 230b8c060fc..1ebbc844b34 100644 --- a/runtime/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/runtime/jobs/Bug_550738.java +++ b/runtime/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/runtime/jobs/Bug_550738.java @@ -134,4 +134,41 @@ public void testReportDoneOncePerSchedule() throws InterruptedException { waitForCompletion(job); } } + + /** + * Test for issue #160: Job.schedule() should work after cancel() when job is running. + * This tests the specific scenario where: + * 1. Job is running + * 2. cancel() is called + * 3. schedule() is called immediately (while still running) + * 4. Job finishes and should reschedule + */ + @Test + public void testCancelThenScheduleWhileRunning() throws InterruptedException { + BusyLoopJob job = new BusyLoopJob(); + try { + for (int i = 0; i < 100; i++) { + CountDownLatch startedLatch = new CountDownLatch(1); + job.started = startedLatch::countDown; + job.schedule(); + assertTrue("Job should start after schedule. Iteration " + i, + startedLatch.await(5, TimeUnit.SECONDS)); + + // While job is running, cancel it and then immediately schedule it again + Thread.sleep(i); + job.cancel(); + job.schedule(); + + // The job should reschedule and not remain in NONE state + // Wait a bit to ensure the rescheduling happens + Thread.sleep(50); + int state = job.getState(); + assertTrue("Job should not be in NONE state after cancel+schedule. Iteration " + i + ", state: " + state, + state != org.eclipse.core.runtime.jobs.Job.NONE); + } + } finally { + job.cancelWithoutRelyingOnFramework = true; + waitForCompletion(job); + } + } }