Fire an event for all tools that have the event bit set. `cb_extra` contains the callback arguments after the code object.
(
vm: &VirtualMachine,
event: u32,
code: &PyRef<PyCode>,
offset: u32,
cb_extra: &[PyObjectRef],
)
| 725 | /// Fire an event for all tools that have the event bit set. |
| 726 | /// `cb_extra` contains the callback arguments after the code object. |
| 727 | fn fire( |
| 728 | vm: &VirtualMachine, |
| 729 | event: u32, |
| 730 | code: &PyRef<PyCode>, |
| 731 | offset: u32, |
| 732 | cb_extra: &[PyObjectRef], |
| 733 | ) -> PyResult<()> { |
| 734 | // Prevent recursive event firing |
| 735 | if FIRING.with(|f| f.get()) { |
| 736 | return Ok(()); |
| 737 | } |
| 738 | |
| 739 | let event_id = event.trailing_zeros() as usize; |
| 740 | let code_id = code.get_id(); |
| 741 | |
| 742 | // C_RETURN and C_RAISE are implicitly enabled when CALL is set. |
| 743 | let check_bit = if event & EVENT_C_RETURN_MASK != 0 { |
| 744 | event | EVENT_CALL |
| 745 | } else { |
| 746 | event |
| 747 | }; |
| 748 | |
| 749 | // Collect callbacks and snapshot the DISABLE sentinel under a single lock. |
| 750 | let (callbacks, disable_sentinel): (Vec<(usize, PyObjectRef)>, Option<PyObjectRef>) = { |
| 751 | let state = vm.state.monitoring.lock(); |
| 752 | let mut cbs = Vec::new(); |
| 753 | for tool in 0..TOOL_LIMIT { |
| 754 | let global = state.global_events[tool]; |
| 755 | let local = state |
| 756 | .local_events |
| 757 | .get(&(tool, code_id)) |
| 758 | .copied() |
| 759 | .unwrap_or(0); |
| 760 | if ((global | local) & check_bit) == 0 { |
| 761 | continue; |
| 762 | } |
| 763 | if state.disabled.contains(&(code_id, offset as usize, tool)) { |
| 764 | continue; |
| 765 | } |
| 766 | if let Some(cb) = state.callbacks.get(&(tool, event_id)) { |
| 767 | cbs.push((tool, cb.clone())); |
| 768 | } |
| 769 | } |
| 770 | (cbs, state.disable.clone()) |
| 771 | }; |
| 772 | |
| 773 | if callbacks.is_empty() { |
| 774 | return Ok(()); |
| 775 | } |
| 776 | |
| 777 | let mut args_vec = Vec::with_capacity(1 + cb_extra.len()); |
| 778 | args_vec.push(code.clone().into()); |
| 779 | args_vec.extend_from_slice(cb_extra); |
| 780 | let args = FuncArgs::from(args_vec); |
| 781 | |
| 782 | FIRING.with(|f| f.set(true)); |
| 783 | let result = (|| { |
| 784 | for (tool, cb) in callbacks { |
no test coverage detected