]> git.ipfire.org Git - thirdparty/HylaFAX.git/commitdiff
This patch fixes a race in the batching/scheduling code of faxq.
authorAidan Van Dyk <aidan@ifax.com>
Wed, 26 Apr 2006 14:04:47 +0000 (14:04 +0000)
committerAidan Van Dyk <aidan@ifax.com>
Wed, 26 Apr 2006 14:04:47 +0000 (14:04 +0000)
The race has always been present, but now that JobControl greatly extends the
time spend operating on the sleepq, the race is highly visible, not requiring
an exact signal during the sleepq processing.

sleepq get's job's added and removed from it asynchronously.  It was never mant
to be "run" through in order.  It was originally only added to or removed from
in the timerExpire() routines in a manner that could not be interrupted.

But with the addition of batching scanning the sleepq for jobs to batch, it now
processes the sleepq in a manner that can be interupted.  JobControl
exasperates this window.

If a "sleeping" job has something happen to it (like it's TTS timer expires),
it will asynchronously go to ready (or some other state), and be put on some
other list.  Once it's on the other list, it's next field can never point to
the sleepiter.head starting position, causing an infinite loop
(sleepiter.notDone() will never be true.

CHANGES
faxd/faxQueueApp.c++

diff --git a/CHANGES b/CHANGES
index 278a17d71acbdf246552e0977304c87bc24a2ead..9fcc0ff41e8164723390811d6351a51326606cec 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,7 @@
 
 Changelog
 
+* Fix faxq sleepq concurrency problem (Bug 745) (26 Apr 2006)
 * Fix runSchedule() concurrency problem (Bug 745) (26 Apr 2006)
 * Fix some of the error paths in the setReadyToRun jobcontrol 
   pipe, fork, and exec calls (BUG 745) (25 Apr 2006)
index 57184552a16d2b9ffc05c660e77a99ba8e0a5e2e..7525ca1c5b6a8f6a02db84e7f5f914082ffcf3c1 100644 (file)
@@ -2467,13 +2467,17 @@ inSchedule = true;
                         * where the queue file is updated.
                         */
                        for (JobIter sleepiter(sleepq); sleepiter.notDone(); sleepiter++) {
-                           if (sleepiter.job().dest != job.dest || sleepiter.job().state != FaxRequest::state_sleeping)
+                           Job& j(sleepiter.job());
+                           if (j.state != FaxRequest::state_pending 
+                               || j.state != FaxRequest::state_sleeping)
+                               break;
+                           if (j.dest != job.dest || j.state != FaxRequest::state_sleeping)
                                continue;
-                           sleepiter.job().stopTTSTimer();
-                           sleepiter.job().tts = now;
-                           sleepiter.job().state = FaxRequest::state_ready;
-                           sleepiter.job().remove();
-                           setReadyToRun(sleepiter.job(), jobCtrlWait);
+                           j.stopTTSTimer();
+                           j.tts = now;
+                           j.state = FaxRequest::state_ready;
+                           j.remove();
+                           setReadyToRun(j, jobCtrlWait);
                        }
 
                        Job* bjob = &job;       // Last batched Job