I faced a situation recently while building a Web application where a Web service that we made requests from would occasionally hang when we made a request. Because we run our application on Linux, we decided to use signals to add a timeout to our request. Because we use Python, we implemented the timeout as a decorator, since we knew we would likely find other places where we needed to add timeouts. A simplified version of this code makes an excellent introduction to how decorators work.
Using signals
First, we should cover how to use signals. Listing 1 shows how to interrupt a runaway function using the alarm function from the signal module.
Listing one: using signals to interrupt runaway functions.
import logging, random, signal logging.basicConfig(level=logging.DEBUG, format="%(levelname)s %(asctime)s %(message)s") class TimeoutException(Exception): "Indicates that the function has taken too long." def handle_alarm(*args): logging.error("Timeout!") raise TimeoutException(*args) def returns_sometimes(): "50/50 chance -- return immediately or hang forever." if random.choice([False, True]): logging.debug("Hurray!") return else: logging.debug("uh oh...") i = 1 while "forever": i += 1 if i == 1000000: logging.debug("another million iterations...") i = 0 def main(): "Show how to cancel a timeout if the function does return in time." # Set the handler for the alarm signal. signal.signal(signal.SIGALRM, handle_alarm) # Schedule an alarm for two seconds in the future. signal.alarm(2) try: logging.debug("About to call the function that returns sometimes...") returns_sometimes() # Now cancel the impending alarm! signal.alarm(0) logging.debug("We got a response back!") except TimeoutException: logging.error("We didn't get a...
Please log in to view this content.
Not Yet a Member?
Register with LinuxMagazine.com and get free access to the entire archive, including: