How to set sigalarm to repeat over and over again in linux? - python

I'm trying to make alarm work over and over again.
My handler is
def handler_SIGALRM(signum, frame):
print "waiting"
signal.alarm(2)
The alarm work only once, even though every time I set it again.
In my code I also use sigchld and sys.exit after the child working.
I'm running it with cygwin.
EDIT:
I need to write a code that will print "waiting" every second, with sigalarm and not loops
I'm an idiot, I edited the wrong code

You put your signal.alarm(2) in a wrong place. See my example below.
import time
import signal
class TimeoutException (Exception):
pass
def signalHandler (signum, frame):
raise TimeoutException ()
timeout_duration = 5
signal.signal (signal.SIGALRM, signalHandler)
for i in range (5):
signal.alarm (timeout_duration)
try:
"""Do something that has a possibility of taking a lot of time
and exceed the timeout_duration"""
time.sleep (20)
except TimeoutException as exc:
print "Notify your program that the timeout_duration has passed"
finally:
#Clean out the alarm
signal.alarm (0)

Related

How to disable interruption with Ctrl+C in cmd/python

I have a program that has quite a few functions, each running on a separate thread.
When the user presses Ctrl+C, only 1 thread crashes with an exception, but because of this, the whole program may not work correctly.
Of course, I can write this construction in each function:
try:
do_something()
except KeyboardInterrupt as e:
pass
but, as I said, there are many functions, perhaps there is an option not to prescribe this construction in each function?
Or is it possible to disable Ctrl+C interrupt in cmd settings?
For example, in the registry. The program creates its own registry key in HKEY_CURRENT_USER\Console\MyProgrammKey
UPD 1
signal.signal(signal.SIGINT, signal.SIG_IGN)
It helped in almost all cases except one: a thread that has an infinite loop with the input() function anyway interrupts.
UPD 2
Here is a sample code
import signal, time
from threading import Thread
def one():
while True:
inp = input("INPUT: ")
def two():
while True:
print("I just printing...")
time.sleep(1)
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal.SIG_IGN)
Thread(target=one).start()
Thread(target=two).start()
UPD 3
Screenshot of exception.
Ctrl+C will send SIGINT signal to program, so you could define a global signal handler to ignore that SIGINT, something like next:
test.py:
import signal, os, time
def handler(signum, frame):
pass
signal.signal(signal.SIGINT, handler)
time.sleep(10)
print("done")
During the program run, if you input Ctrl+c, the program will ignore it, and continue to run, finally print done:
$ python3 test.py
^Cdone

Operation time limit

is there a way to time limit the oparations in python, eg:
try:
cmds.file( file, o=1, pmt=0 )
except:
print "Sorry, run out of time"
pass
If you're on Mac or a Unix-based system, you can use signal.SIGALRM to forcibly time out functions that take too long, so your code would look like:
import signal
class TimeoutException(Exception): # custom exception
pass
def timeout_handler(signum, frame): # raises exception when signal sent
raise TimeoutException
# Makes it so that when SIGALRM signal sent, it calls the function timeout_handler, which raises your exception
signal.signal(signal.SIGALRM, timeout_handler)
# Start the timer. Once 5 seconds are over, a SIGALRM signal is sent.
signal.alarm(5)
try:
cmds.file( file, o=1, pmt=0 )
except TimeoutException:
print "Sorry, run out of time" # you don't need pass because that's in the exception definition
Basically, you're creating a custom exception that's raised when the after the time limit is up (i.e., the SIGALRM is sent). You can of course tweak the time limit.

How to set timeout for thread in case of no response and terminate the thread?

Let's say we have a code sample as below which prints hello, world after 5 seconds. I want a way to check if Timer thread took more than 5 seconds then terminate the thread.
from threading import Timer
from time import sleep
def hello():
sleep(50)
print "hello, world"
t = Timer(5, hello)
# after 5 seconds, "hello, world" will be printed
t.start()
In the above code block hello will take more than 5 seconds to process.
consider hello function, a call to outside server that returns no response and even no exception for timeout or anything! I wanted to simulate the issue with sleep function.
You can use signal and call its alarm method. An exception (which you can handle) will be raised after the timeout time has passed. See an (incomplete) example below.
import signal
class TimeoutException (Exception):
pass
def signalHandler (signum, frame):
raise TimeoutException ()
timeout_duration = 5
signal.signal (signal.SIGALRM, signalHandler)
signal.alarm (timeout_duration)
try:
"""Do something that has a possibility of taking a lot of time
and exceed the timeout_duration"""
except TimeoutException as exc:
"Notify your program that the timeout_duration has passed"
finally:
#Clean out the alarm
signal.alarm (0)
You can read more about Python's signal here https://docs.python.org/2/library/signal.html.

Can I make use of an interrupt to print a status while still continue process?

In python, is it possible to make use of KeyboardInterrupt or CTRL+C to print a status message, possibly like printing content of a variable and then continuing with the execution?
Or will Interrupts always kill the process?
An example of what I would like to do:
def signal_handler(signum, frame):
global interrupted
interrupted = True
while true:
update(V)
if interrupted:
print V
You can do this using a signal handler:
import signal
def sigint_handler(signum, frame):
print "my_variable =", frame.f_locals.get("my_variable", None)
signal.signal(signal.SIGINT, sigint_handler)
Now interrupting the script calls the handler, which prints the variable, fishing it out of the current stack frame. The script then continues.
It can be done. The signal library provides this functionality, and it pretty much goes the way you prototyped.
import signal
interrupted = False
def signal_handler(signum, frame):
global interrupted
interrupted = True
signal.signal(signal.SIGINT, signal_handler)
while true:
update(V)
if interrupted:
print V
Pressing ctrl+c raises KeyboardInterrupt.
Catch KeyboardInterrupt and print a message from it, or use a state variable like you have above.
See: Capture Control-C in Python

Python use signal alarm in order to limit function execution time dosnt always stop the method

I need to limit function execution time, so i followed Josh Lee answer
try:
with time_limit(10):
long_function_call()
except TimeoutException, msg:
print "Timed out!"
where long_function_call() is a selenium webdriver function that interact with a page and do some operations.
def long_function_call(self, userName, password):
driver = self.initDriver()
try:
driver.get("https://yyyy.com")
time.sleep(2)
if not self.isHttps(driver.current_url):
isHttps = False
driver.find_element_by_id("i015516").clear()
time.sleep(5)
if 'https://yyy.com' not in driver.current_url:
self.raiseFailedToLogin('yyy')
except Exception as e:
self.raiseException('yyy',e)
finally:
driver.close()
driver.quit()
return 'yyyy'
In most cases , when function execution time exceed the signal timeout signal was sent and method stopped, but in some cases the method exceed the timeout and didnt stop. it seems that selenium is hang.(the firefox is open and nothing is done in it).
I tried to pause debugger in these cases , but pause didn't show me where it hang.
If i close the selenium firefox than the debug pause stop on this method:
_read_status [httplib.py:366]
begin [httplib.py:407]
getresponse [httplib.py:1030]
do_open [urllib2.py:1180]
http_open [urllib2.py:1207]
def _read_status(self):
# Initialize with Simple-Response defaults
line = self.fp.readline()
if self.debuglevel > 0: ################Hang here
Any idea why in some cases signal alarm with selenium didnt work? (i dont think they catch interrupt).
This is a very interesting problem you are facing. I've created an example which can demonstrate some of the issues you may face when using with time_limit. If you run the code below you may expect that after 1 second a TimeoutException will be raised which will then exit python and the running thread as well as the xterm should all exit. What happens is after one second the TimeoutException is raised and you will see the "Timed out!" appear in the terminal but both the thread and xterm will continue their execution. This maybe the type of scenario you are facing with selenium. I don't know how selenium is implemented but the firefox process must be spawned in a way similar to how xterm is in the example.
simple approach
import time, os, sys, subprocess, threading
def worker():
for i in range(30):
print i
time.sleep(0.1)
try:
with time_limit(1):
threading.Thread(target=worker).start()
subprocess.check_output('/usr/bin/xterm')
except TimeoutException, msg:
print "Timed out!"
a potential solution to this problem is the following code. It will kill all children of this python program which would kill xterm in this case, and then it would kill itself. This is of course a forceful way to exit but would guarantee everything ended on timeout.
kill them all
subprocess.call('pkill -P %s' % os.getpid(), shell=True)
subprocess.call('kill -9 %s' % os.getpid(), shell=True)
taking into account your comments below another approach would be to have another thread that would perform the kill operations if an operation in the main thread exceeded the specified timeout. This is an implementation of that approach with an example call.
thread that watches and kills on timeout
import time, os
from subprocess import check_output, call
from threading import Thread
from contextlib import contextmanager
def wait_thread(active, duration):
start = time.time()
while active[0] and time.time() - start < duration:
time.sleep(0.1)
if active[0]:
call('pkill -P %s' % os.getpid(), shell=True)
call('kill -9 %s' % os.getpid(), shell=True)
#contextmanager
def wait(duration):
active = [True]
Thread(target=wait_thread, args=(active, duration)).start()
yield
active[0] = False
with wait(1):
time.sleep(0.5)
print 'finished safely before timeout'
with wait(1):
call('/usr/bin/xterm')

Categories