stopit icon indicating copy to clipboard operation
stopit copied to clipboard

Trouble Nesting stopit

Open NoRaincheck opened this issue 7 years ago • 3 comments

Hi,

I'm having a bit of trouble nesting timeouts. Platforms tested:

  • Windows 10 Pro
  • Mac OSX

My shortest reproducible solution is here:

from stopit import ThreadingTimeout as Timeout
import time

def print_stuff(idx):
    while True:
        time.sleep(1)
        print(idx)


def test_this():
    t0 = time.time()
    for idx in range(5):
        with Timeout(5) as timeout_inner:
            print_stuff(idx)
    return time.time() - t0

with Timeout(10) as timeout_outer:
    res = test_this()

assert res < 15

Where the output is:

0
0
0
0
1
1
1
1
2
2
2
2
3
3
3
3
4
4
4
4
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-28-abee5adecac5> in <module>()
     18     res = test_this()
     19 
---> 20 assert res < 15

AssertionError: 

NoRaincheck avatar Mar 31 '18 03:03 NoRaincheck

Please read the README section about the timeout accuracy issue when using thread blocking funcs like time.sleep(xxx) within a Timeout context manager.

glenfant avatar Apr 04 '18 15:04 glenfant

I don't believe this is a timing issue.

My point is that nesting threading blocks literally do not work. Could you provide a pattern or an example where it does work?

I could replace the for loop with an infinite loop and it would never terminate.

As an example this would never terminate

from stopit import ThreadingTimeout as Timeout
import time

def print_stuff(idx):
    while True:
        time.sleep(1)
        print(idx)


def test_this():
    t0 = time.time()
    while True:
        with Timeout(5) as timeout_inner:
            print_stuff(1)
    return time.time() - t0

with Timeout(10) as timeout_outer:
    res = test_this()

NoRaincheck avatar Apr 05 '18 00:04 NoRaincheck

Hi, I had the same issue, and it's related with the fact that the ThreadingTimeout set a timer on the same thread_id (https://github.com/glenfant/stopit/blob/master/src/stopit/threadstop.py#L45). Only way to solve this is to set-up different thread, or find a way to raise different exception per context manager.

lpyparmentier avatar Nov 19 '20 10:11 lpyparmentier