Commit 4c1402b
committed
Fix race condition in parallel tool execution with targeted locking
Add asyncio.Lock specifically in _call_tools() to prevent race conditions during
parallel tool execution, rather than adding overhead to every usage increment.
Implementation:
- Created asyncio.Lock in _call_tools() where parallel execution occurs
- Used ContextVar to pass lock to ToolManager.handle_call() during parallel context
- Guard usage.incr(RunUsage(tool_calls=1)) only when executing tools in parallel
- Removed unnecessary lock from RunUsage class for better performance
Why this works:
The race condition occurs when multiple asyncio tasks call usage.incr()
concurrently. Even though asyncio is single-threaded, tasks can interleave
at await points, causing non-atomic read-modify-write operations
(usage.tool_calls += 1) to lose increments.
By guarding only the parallel tool execution path with a lock, we:
- Prevent the race condition where it actually occurs
- Avoid performance overhead in sequential/non-parallel execution
- Maintain clean serialization (no lock in dataclass)
- Achieve 100% test coverage
Changes:
- pydantic_ai_slim/pydantic_ai/_agent_graph.py: Add usage_lock in _call_tools()
- pydantic_ai_slim/pydantic_ai/_tool_manager.py: Use lock from ContextVar
- pydantic_ai_slim/pydantic_ai/usage.py: Simplified RunUsage.incr() and __add__()
- Added pass statement for full branch coverage
- tests/test_usage_limits.py: Added comprehensive test coverage
- test_race_condition_parallel_tool_calls() with 20 iterations, 10 parallel tools
- Enhanced test_run_usage_with_request_usage() for empty/non-empty details
- Fixed snapshot mismatches in test files
- Fixed formatting/trailing whitespace issues
Test coverage:
- Added test_race_condition_parallel_tool_calls() that fails on main
- All existing tests pass with updated snapshots
- 100% branch coverage achieved for usage.py
Resolves #31201 parent 78fb707 commit 4c1402b
File tree
7 files changed
+180
-71
lines changed- pydantic_ai_slim/pydantic_ai
- models
- tests
- models
7 files changed
+180
-71
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
408 | 408 | | |
409 | 409 | | |
410 | 410 | | |
411 | | - | |
| 411 | + | |
412 | 412 | | |
413 | 413 | | |
414 | 414 | | |
| |||
426 | 426 | | |
427 | 427 | | |
428 | 428 | | |
429 | | - | |
| 429 | + | |
430 | 430 | | |
431 | 431 | | |
432 | 432 | | |
| |||
437 | 437 | | |
438 | 438 | | |
439 | 439 | | |
440 | | - | |
| 440 | + | |
441 | 441 | | |
442 | | - | |
| 442 | + | |
443 | 443 | | |
444 | 444 | | |
445 | 445 | | |
| |||
481 | 481 | | |
482 | 482 | | |
483 | 483 | | |
484 | | - | |
| 484 | + | |
485 | 485 | | |
486 | 486 | | |
487 | 487 | | |
| |||
895 | 895 | | |
896 | 896 | | |
897 | 897 | | |
| 898 | + | |
| 899 | + | |
898 | 900 | | |
899 | 901 | | |
900 | 902 | | |
| |||
904 | 906 | | |
905 | 907 | | |
906 | 908 | | |
907 | | - | |
908 | | - | |
909 | | - | |
910 | | - | |
911 | | - | |
912 | | - | |
913 | | - | |
| 909 | + | |
| 910 | + | |
914 | 911 | | |
915 | | - | |
916 | | - | |
917 | | - | |
918 | | - | |
919 | | - | |
920 | | - | |
921 | | - | |
922 | | - | |
923 | | - | |
924 | | - | |
925 | | - | |
926 | | - | |
927 | | - | |
928 | | - | |
929 | | - | |
930 | | - | |
931 | | - | |
932 | | - | |
933 | | - | |
934 | | - | |
935 | | - | |
936 | | - | |
937 | | - | |
938 | | - | |
939 | | - | |
| 912 | + | |
940 | 913 | | |
941 | | - | |
942 | | - | |
943 | | - | |
944 | | - | |
945 | | - | |
946 | | - | |
947 | | - | |
948 | | - | |
949 | | - | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
950 | 922 | | |
951 | | - | |
952 | | - | |
953 | | - | |
954 | | - | |
955 | | - | |
956 | | - | |
957 | | - | |
958 | | - | |
959 | | - | |
960 | | - | |
961 | | - | |
962 | | - | |
963 | | - | |
964 | | - | |
965 | | - | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
966 | 959 | | |
967 | 960 | | |
968 | | - | |
969 | | - | |
970 | | - | |
971 | | - | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
972 | 977 | | |
973 | | - | |
974 | | - | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
975 | 988 | | |
976 | 989 | | |
977 | 990 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
21 | 22 | | |
22 | 23 | | |
23 | 24 | | |
| 25 | + | |
24 | 26 | | |
25 | 27 | | |
26 | 28 | | |
| |||
234 | 236 | | |
235 | 237 | | |
236 | 238 | | |
237 | | - | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
238 | 246 | | |
239 | 247 | | |
240 | 248 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1178 | 1178 | | |
1179 | 1179 | | |
1180 | 1180 | | |
1181 | | - | |
| 1181 | + | |
1182 | 1182 | | |
1183 | 1183 | | |
1184 | 1184 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
198 | 198 | | |
199 | 199 | | |
200 | 200 | | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
201 | 205 | | |
202 | 206 | | |
203 | 207 | | |
204 | 208 | | |
205 | 209 | | |
206 | 210 | | |
| 211 | + | |
| 212 | + | |
207 | 213 | | |
208 | 214 | | |
209 | 215 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2600 | 2600 | | |
2601 | 2601 | | |
2602 | 2602 | | |
| 2603 | + | |
2603 | 2604 | | |
2604 | 2605 | | |
2605 | 2606 | | |
| |||
2620 | 2621 | | |
2621 | 2622 | | |
2622 | 2623 | | |
| 2624 | + | |
2623 | 2625 | | |
2624 | 2626 | | |
2625 | 2627 | | |
| |||
2644 | 2646 | | |
2645 | 2647 | | |
2646 | 2648 | | |
| 2649 | + | |
2647 | 2650 | | |
2648 | 2651 | | |
2649 | 2652 | | |
| |||
2664 | 2667 | | |
2665 | 2668 | | |
2666 | 2669 | | |
| 2670 | + | |
2667 | 2671 | | |
2668 | 2672 | | |
2669 | 2673 | | |
| |||
2693 | 2697 | | |
2694 | 2698 | | |
2695 | 2699 | | |
| 2700 | + | |
2696 | 2701 | | |
2697 | 2702 | | |
2698 | 2703 | | |
| |||
2710 | 2715 | | |
2711 | 2716 | | |
2712 | 2717 | | |
| 2718 | + | |
2713 | 2719 | | |
2714 | 2720 | | |
2715 | 2721 | | |
| |||
2730 | 2736 | | |
2731 | 2737 | | |
2732 | 2738 | | |
| 2739 | + | |
2733 | 2740 | | |
2734 | 2741 | | |
2735 | 2742 | | |
| |||
2758 | 2765 | | |
2759 | 2766 | | |
2760 | 2767 | | |
| 2768 | + | |
2761 | 2769 | | |
2762 | 2770 | | |
2763 | 2771 | | |
| |||
2796 | 2804 | | |
2797 | 2805 | | |
2798 | 2806 | | |
| 2807 | + | |
2799 | 2808 | | |
2800 | 2809 | | |
2801 | 2810 | | |
| |||
2831 | 2840 | | |
2832 | 2841 | | |
2833 | 2842 | | |
| 2843 | + | |
2834 | 2844 | | |
2835 | 2845 | | |
2836 | 2846 | | |
| |||
2849 | 2859 | | |
2850 | 2860 | | |
2851 | 2861 | | |
| 2862 | + | |
2852 | 2863 | | |
2853 | 2864 | | |
2854 | 2865 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3346 | 3346 | | |
3347 | 3347 | | |
3348 | 3348 | | |
3349 | | - | |
| 3349 | + | |
3350 | 3350 | | |
3351 | 3351 | | |
3352 | 3352 | | |
| |||
0 commit comments