| 118 | |
| 119 | @contextlib.contextmanager |
| 120 | def start_threads(threads, unlock=None): |
| 121 | try: |
| 122 | import faulthandler |
| 123 | except ImportError: |
| 124 | # It isn't supported on subinterpreters yet. |
| 125 | faulthandler = None |
| 126 | threads = list(threads) |
| 127 | started = [] |
| 128 | try: |
| 129 | try: |
| 130 | for t in threads: |
| 131 | t.start() |
| 132 | started.append(t) |
| 133 | except: |
| 134 | if support.verbose: |
| 135 | print("Can't start %d threads, only %d threads started" % |
| 136 | (len(threads), len(started))) |
| 137 | raise |
| 138 | yield |
| 139 | finally: |
| 140 | try: |
| 141 | if unlock: |
| 142 | unlock() |
| 143 | endtime = time.monotonic() |
| 144 | for timeout in range(1, 16): |
| 145 | endtime += 60 |
| 146 | for t in started: |
| 147 | t.join(max(endtime - time.monotonic(), 0.01)) |
| 148 | started = [t for t in started if t.is_alive()] |
| 149 | if not started: |
| 150 | break |
| 151 | if support.verbose: |
| 152 | print('Unable to join %d threads during a period of ' |
| 153 | '%d minutes' % (len(started), timeout)) |
| 154 | finally: |
| 155 | started = [t for t in started if t.is_alive()] |
| 156 | if started: |
| 157 | if faulthandler is not None: |
| 158 | faulthandler.dump_traceback(sys.stdout) |
| 159 | raise AssertionError('Unable to join %d threads' % len(started)) |
| 160 | |
| 161 | |
| 162 | class catch_threading_exception: |