Setting a timeout for mechanize.Browser
Question: I was perusing the question posted here:

[What should I do if socket.setdefaulttimeout() is not
working?](http://stackoverflow.com/questions/8464391/what-should-i-do-if-
socket-setdefaulttimeout-is-not-working)

to try and come up with a solution to kill requests when my
`mechanize.Browser` object is taking too long, and I have been experimenting
with the first solution in tomasz's edit (reposted here for clarity):

    
    
    import signal, time
    
    def request(arg):
      """Your http request"""
      time.sleep(2)
      return arg
    
    class Timeout():
      """Timeout class using ALARM signal"""
      class Timeout(Exception): pass
    
      def __init__(self, sec):
        self.sec = sec
    
      def __enter__(self):
        signal.signal(signal.SIGALRM, self.raise_timeout)
        signal.alarm(self.sec)
    
      def __exit__(self, *args):
        signal.alarm(0) # disable alarm
    
      def raise_timeout(self, *args):
        raise Timeout.Timeout()
    
    # Run block of code with timeouts
    try:
      with Timeout(3):
        print request("Request 1")
      with Timeout(1):
        print request("Request 2")
    except Timeout.Timeout:
      print "Timeout"
    
    # Prints "Request 1" and "Timeout"
    

When I run this from my terminal using `python timeout.py` (version is`Python
2.7.2+` and I am on Ubuntu 11.10 Oneiric Ocelot), there is no exception
thrown- instead it simply prints

    
    
    Request 1
    Request 2
    

Could someone please explain how to fix this? An explanation of what's going
on with those `signal.alarm` and `signal.signal` calls would be awesome too.

Thank you very much for your time!

EDIT:

Running `strace -f python timeout.py` yields:

    
    
    alarm(3)                                = 0
    select(0, NULL, NULL, NULL, {2, 0})     = 0 (Timeout)
    fstat64(1, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
    mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb740c000
    alarm(0)                                = 1
    rt_sigaction(SIGALRM, {0x812f450, [], 0}, {0x812f450, [], 0}, 8) = 0
    alarm(1)                                = 0
    select(0, NULL, NULL, NULL, {2, 0})     = 0 (Timeout)
    alarm(0)                                = 0
    rt_sigaction(SIGINT, {SIG_DFL, [], 0}, {0x812f450, [], 0}, 8) = 0
    rt_sigaction(SIGALRM, {SIG_DFL, [], 0}, {0x812f450, [], 0}, 8) = 0
    write(1, "Request 1\nRequest 2\n", 20)  = 20
    exit_group(0)                           = ?
    


Answer: If you want to know what happens here, please try:

    
    
    $ strace -f python timeout.py
    

For me (running Debian 6 with python 2.6) this works. strace output of the
important part:

    
    
    alarm(3)                                = 0
    select(0, NULL, NULL, NULL, {2, 0})     = 0 (Timeout)
    fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 15), ...}) = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =  x7f0fbbe06000
    write(1, "Request 1\n", 10Request 1)             = 10
    alarm(0)                                = 1
    rt_sigaction(SIGALRM, {0x4d0a90, [], SA_RESTORER, 0x7f0fbb9deff0}, {0x4d0a90, [], SA_RESTORER, 0x7f0fbb9deff0}, 8) = 0
    alarm(1)                                = 0
    select(0, NULL, NULL, NULL, {2, 0})     = ? ERESTARTNOHAND (To be restarted)
    --- SIGALRM (Alarm clock) @ 0 (0) ---
    rt_sigreturn(0xffffffff)                = -1 EINTR (Interrupted system call)
    alarm(0)                                = 0
    write(1, "Timeout\n", 8Timeout
    )                = 8
    

alarm(3) is called; Request 1 comes through; alarm(1) is called which gives a
Timeout.

