Tcl Library Source Code

View Ticket
Login
Ticket UUID: dae6b527bc159a14c914c3d4eae46ac99a31b9be
Title: Declaring a cron handler inside a cron command creates and infinte loop
Type: Bug Version: 1.17
Submitter: anonymous Created on: 2015-09-18 21:45:03
Subsystem: cron Assigned To: hypnotoad
Priority: 5 Medium Severity: Important
Status: Closed Last Modified: 2015-12-10 16:39:41
Resolution: Fixed Closed By: hypnotoad
    Closed on: 2015-12-10 16:39:41
Description:
Okay! So when defining cron handlers, you cannot nest them:
=========================================================
#! /usr/bin/tclsh
package require cron

# Done timer
::cron::in done 20 {incr ::done}

# Ten second timer
::cron::in ten_seconds 10 {
    puts "10 second timer triggered!"
    # Nested timer
    ::cron::in five_seconds 5 {
        puts "5 seconds triggered!"
    }
}

vwait ::done
=========================================================
Gives us this output:
=========================================================
second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
10 second timer triggered!
5 seconds triggered!
[hooga@samserv01 ~]$
=========================================================

If you instead turn the inner cron statement to an after Xms y, it works as expected:
=========================================================
#! /usr/bin/tclsh
package require cron

# Done timer
::cron::in done 20 {incr ::done}

# Ten second timer
::cron::in ten_seconds 10 {
    puts "10 second timer triggered!"
    # Nested timer
    after 5000 {
        puts "After 5 seconds triggered!"
    }
}

vwait ::done
=========================================================

=========================================================
[hooga@samserv01 ~]$ ./cron.tcl
10 second timer triggered!
After 5 seconds triggered!
[hooga@samserv01 ~]$
=========================================================
User Comments: aku added on 2015-12-10 05:34:40:
Revision [c4c84d1854] claims to be a fix.
If so, should this ticket not be closed ?

hypnotoad added on 2015-12-04 19:49:12:
I have fixed the bug in checkin [c4c84d18547f70193d0cfc9ff434aebf20d1300c].

The trick was to add a lock variable that is true while periodic task scripts are actively processed. When
true, this flag turns cron::wake into a noop. (cron::wake is intended to immediately rouse the system
when a new task hits the manager.)

Now when I run the test script I get:

=========================================================
baccarat:cron seandeelywoods$ tclsh inf.tcl 
10 second timer triggered!
5 seconds triggered!
=========================================================

hypnotoad added on 2015-12-04 19:11:11:
Well that’s no fun at all. I’ll inject a mutex to at least throw an error if someone attempts that in the future.

Thanks for catching it!

—Sean