@@ -268,6 +268,16 @@ private void doReschedule(final String jobId, long executionTime, long nextExecu
268268 this .store .store (update );
269269 }
270270
271+ private void doSchedule (final List <Closure > toSchedule ) {
272+ for (Closure closure : toSchedule ) {
273+ try {
274+ closure .run ();
275+ } catch (final Exception e ) {
276+ LOG .warn ("Failed to schedule job" , e );
277+ }
278+ }
279+ }
280+
271281 private void doRemove (final List <Closure > toRemove ) throws IOException {
272282 for (Closure closure : toRemove ) {
273283 closure .run ();
@@ -727,6 +737,7 @@ protected void mainLoop() {
727737 // needed before firing the job event.
728738 List <Closure > toRemove = new ArrayList <>();
729739 List <Closure > toReschedule = new ArrayList <>();
740+ List <Closure > toSchedule = new ArrayList <>();
730741 try {
731742 this .store .readLockIndex ();
732743
@@ -776,12 +787,18 @@ protected void mainLoop() {
776787 // we have a separate schedule to run at this time
777788 // so the cron job is used to set of a separate schedule
778789 // hence we won't fire the original cron job to the
779- // listeners but we do need to start a separate schedule
780- String jobId = ID_GENERATOR .generateId ();
781- ByteSequence payload = getPayload (job .getLocation ());
782- schedule (jobId , payload , "" , job .getDelay (), job .getPeriod (), job .getRepeat ());
783- waitTime = job .getDelay () != 0 ? job .getDelay () : job .getPeriod ();
784- this .scheduleTime .setWaitTime (waitTime );
790+ // listeners, but we do need to start a separate schedule
791+ toSchedule .add (() -> {
792+ try {
793+ String jobId = ID_GENERATOR .generateId ();
794+ ByteSequence payload = getPayload (job .getLocation ());
795+ schedule (jobId , payload , "" , job .getDelay (), job .getPeriod (), job .getRepeat ());
796+ } catch (Exception e ) {
797+ LOG .warn ("Failed to schedule cron follow-up job" , e );
798+ }
799+ });
800+ long wait = job .getDelay () != 0 ? job .getDelay () : job .getPeriod ();
801+ this .scheduleTime .setWaitTime (wait );
785802 }
786803 } else {
787804 toRemove .add (() -> doRemove (executionTime , job .getJobId ()));
@@ -797,6 +814,10 @@ protected void mainLoop() {
797814 } finally {
798815 this .store .readUnlockIndex ();
799816
817+ // deferred execution of all jobs to be scheduled to avoid deadlock with indexLock
818+ doSchedule (toSchedule );
819+
820+ // now reschedule all jobs that need rescheduling
800821 doReschedule (toReschedule );
801822
802823 // now remove all jobs that have not been rescheduled,
@@ -805,6 +826,7 @@ protected void mainLoop() {
805826 }
806827
807828 this .scheduleTime .pause ();
829+
808830 } catch (Exception ioe ) {
809831 LOG .error ("{} Failed to schedule job" , this .name , ioe );
810832 try {
0 commit comments