Synchronisation issues when sending ABORT signal to a job
Consider the following code:
DbControl dc = ... Job job = Job.getById(dc, jobId); job.getSignalTransporter().send(Signal.ABORT); dc.commit();
It is the standard way of sending the ABORT signal to a job. It is for example used by the web client. There is one problem that is not easy to spot. The source of the problem is the
job.getSignalTransporter().send(Signal.ABORT) line. The signal transporter returned by the
Job.getSignalTransporter() method is an instance of the inner class
Job$JobSignalTransporter. This class detects the
Signal.ABORT signal and sets the
Job.Status.ABORTING. This is all fine, except the changed property is not written to the database until
dc.commit() is called.
During that time, it is possible that the signal has already been delivered to the plug-in which has exited and changed the status to
Job.Status.ERROR. Thus, it may happen that the commit overwrites the status and the job is left in the
ABORTING status forever.
The correct way to handle this is to make sure that the status of the job is updated in the correct order. This means that the signal can't be sent until the commit has been done. The simplest way is to get rid of the inner class and let the web client handle the status change first, commit and then send the signal. The elegant way is to make the internal class aware of the transaction handling and delay the sending of the signal until