2

I'm writing Python 2.7 that need to run sub-process and terminate it if the subprocess user time exceeded max time.
The definiton for user time can be found in this answer to What do 'real', 'user' and 'sys' mean in the output of time(1)?
So far I have this:

Code

from multiprocessing import Process
import time

def do_something():
    pass

def run_process_limited_time(max_seconds):

    # init Process
    p = Process(target=do_something, args=())

    # start process
    p.start()

    run_time = 0;
    sleep_time = 1;

    while 1:

        # sleep for sleep_time seconds
        time.sleep(sleep_time)

        # increase run time
        run_time += sleep_time

        # if process is not alive, we can break the loop
        if not p.is_alive():
            break

        # if process is still alive after max_seconds, kill it!
        # TBD - condition is not sufficient 
        elif run_time > max_seconds:
            p.terminate()
            break

def main():
    run_process_limited_time(10)

if __name__ == "__main__":
    main()

Question

the condition elif run_time > max_seconds is not good enough. I'd like to check that max seconds does not exceed user time only. Not sure I can do it using Process module but I'm open to new ideas.

Community
  • 1
  • 1
idanshmu
  • 5,061
  • 6
  • 46
  • 92

2 Answers2

1

This is because you're using an elif statement where you should be using an if statement:

from multiprocessing import Process
import time


def do_something():
    while True:
        time.sleep(100)


def run_process_limited_time(max_seconds):

    # init Process
    p = Process(target=do_something, args=())

    # start process
    p.start()

    run_time = 0
    sleep_time = 1

    while True:
        time.sleep(sleep_time)
        run_time += sleep_time
        if not p.is_alive():
            break

        if run_time > max_seconds:
            print "Process was terminated, due to exceeding max time"
            p.terminate()
            break


def main():
    run_process_limited_time(10)

if __name__ == "__main__":
    main()

Try the above, the process should be terminated.

Games Brainiac
  • 80,178
  • 33
  • 141
  • 199
1

An alternative using the resource module. Handling the timeout can be achieved using the signal module. Returning results can be handled in a variety of ways, some of which are described in the multiprocessing documentation.

from multiprocessing import Process
import time
import resource
import signal

def do_something():
    import resource
    resource.setrlimit(resource.RLIMIT_CPU, (1,1))
    def f(signo, stackframe):
        raise Exception('stop')
    signal.signal(signal.SIGXCPU, f)
    try:
        while 1:
            print 'hello'
    except:
        print 'aborted'

def run_process_limited_time(function):

    # init Process
    p = Process(target=function, args=())

    # start process
    p.start()

    p.join(2)
    p.terminate()


if __name__ == "__main__":
    run_process_limited_time(do_something)
Andrew Walker
  • 40,984
  • 8
  • 62
  • 84
  • Thanks. How do I get indication whether do_somthing was terminated or finished within the max time? – idanshmu Dec 17 '13 at 10:12
  • I guess with your solution, I no longer need to start a new process. run_process_limited_time() is obsolete now since it does not have any control on do_something execution time. we can just call do_something() directly. – idanshmu Dec 17 '13 at 10:49
  • You are correct if you only need to do this for one process. This approach might still be useful in cases where you want to spin up multiple worker process and manage timeouts for all of them in parallel (but I'm not entirely sure how well signals & multiprocessing mix). – Andrew Walker Dec 17 '13 at 10:52