| 566 | } |
| 567 | |
| 568 | fn run_thread(func: ArgCallable, args: FuncArgs, vm: &VirtualMachine) { |
| 569 | // Increment thread count when thread actually starts executing |
| 570 | vm.state.thread_count.fetch_add(1); |
| 571 | |
| 572 | match func.invoke(args, vm) { |
| 573 | Ok(_obj) => {} |
| 574 | Err(e) if e.fast_isinstance(vm.ctx.exceptions.system_exit) => {} |
| 575 | Err(exc) => { |
| 576 | vm.run_unraisable( |
| 577 | exc, |
| 578 | Some("Exception ignored in thread started by".to_owned()), |
| 579 | func.into(), |
| 580 | ); |
| 581 | } |
| 582 | } |
| 583 | for lock in SENTINELS.take() { |
| 584 | if lock.mu.is_locked() { |
| 585 | unsafe { lock.mu.unlock() }; |
| 586 | } |
| 587 | } |
| 588 | // Clean up thread-local storage while VM context is still active |
| 589 | // This ensures __del__ methods are called properly |
| 590 | cleanup_thread_local_data(); |
| 591 | // Clean up frame tracking |
| 592 | crate::vm::thread::cleanup_current_thread_frames(vm); |
| 593 | vm.state.thread_count.fetch_sub(1); |
| 594 | } |
| 595 | |
| 596 | /// Clean up thread-local data for the current thread. |
| 597 | /// This triggers __del__ on objects stored in thread-local variables. |