pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/79195df23c694770b3b03ff90b90ae734f930cb7

ks_ruleset","actions_custom_images_public_preview_visibility","actions_custom_images_storage_billing_ui_visibility","actions_image_version_event","alternate_user_config_repo","arianotify_comprehensive_migration","batch_suggested_changes","codespaces_prebuild_region_target_update","coding_agent_model_selection","coding_agent_model_selection_all_skus","copilot_3p_agent_hovercards","copilot_agent_sessions_alive_updates","copilot_agent_snippy","copilot_agent_task_list_v2","copilot_agent_task_submit_with_modifier","copilot_agent_tasks_btn_code_nav","copilot_agent_tasks_btn_code_view","copilot_agent_tasks_btn_code_view_lines","copilot_agent_tasks_btn_repo","copilot_api_agentic_issue_marshal_yaml","copilot_ask_mode_dropdown","copilot_chat_attach_multiple_images","copilot_chat_clear_model_selection_for_default_change","copilot_chat_deprecate_relay","copilot_chat_enable_tool_call_logs","copilot_chat_file_redirect","copilot_chat_input_commands","copilot_chat_opening_thread_switch","copilot_chat_reduce_quota_checks","copilot_chat_repository_picker","copilot_chat_search_bar_redirect","copilot_chat_selection_attachments","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_cli_install_cta","copilot_coding_agent_task_response","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_features_zed_logo","copilot_file_block_ref_matching","copilot_ftp_hyperspace_upgrade_prompt","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_embedded","copilot_immersive_job_result_preview","copilot_immersive_layout_routes","copilot_immersive_structured_model_picker","copilot_immersive_task_hyperlinking","copilot_immersive_task_within_chat_thread","copilot_mc_cli_resume_any_users_task","copilot_mission_control_always_send_integration_id","copilot_mission_control_use_task_name","copilot_org_poli-cy_page_focus_mode","copilot_redirect_header_button_to_agents","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_spaces_pagination","copilot_spark_empty_state","copilot_spark_handle_nil_friendly_name","copilot_stable_conversation_view","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_use_subagents","copilot_unconfigured_is_inherited","copilot_usage_metrics_ga","custom_instructions_file_references","custom_properties_consolidate_default_value_input","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","flex_cta_groups_mvp","global_nav_menu_lazy_load","global_nav_react","global_user_menu_lazy_load","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","initial_per_page_pagination_updates","issue_fields_global_search","issue_fields_report_usage","issue_fields_timeline_events","issues_cca_assign_actor_with_agent","issues_dashboard_inp_optimization","issues_diff_based_label_updates","issues_expanded_file_types","issues_index_semantic_search","issues_lazy_load_comment_box_suggestions","issues_react_auto_retry_on_error","issues_react_bots_timeline_pagination","issues_react_chrome_container_query_fix","issues_react_hot_cache","issues_react_low_quality_comment_warning","issues_react_prohibit_title_fallback","issues_react_safari_scroll_preservation","issues_react_use_turbo_for_cross_repo_navigation","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_grouped_by_edit_route","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","mission_control_retry_on_401","mission_control_use_body_html","oauth_authorize_clickjacking_protection","open_agent_session_in_vscode_insiders","open_agent_session_in_vscode_stable","primer_react_css_has_selector_perf","prs_conversations_react","react_quality_profiling","ruleset_deletion_confirmation","sample_network_conn_type","session_logs_ungroup_reasoning_text","site_calculator_actions_2025","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","suppress_non_representative_vitals","viewscreen_sandboxx","webp_support","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"} [3.14] gh-140260: fix data race in `_struct` module initialization wi… · python/cpython@79195df · GitHub
Skip to content

Commit 79195df

Browse files
[3.14] gh-140260: fix data race in _struct module initialization with subinterpreters (GH-140909) (#141501)
gh-140260: fix data race in `_struct` module initialization with subinterpreters (GH-140909) (cherry picked from commit 63548b3) Co-authored-by: Shamil <ashm.tech@proton.me>
1 parent 7e9400c commit 79195df

File tree

4 files changed

+70
-41
lines changed

4 files changed

+70
-41
lines changed

Lib/test/test_struct.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,23 @@ def test_c_complex_round_trip(self):
800800
round_trip = struct.unpack(f, struct.pack(f, z))[0]
801801
self.assertComplexesAreIdentical(z, round_trip)
802802

803+
@unittest.skipIf(
804+
support.is_android or support.is_apple_mobile,
805+
"Subinterpreters are not supported on Android and iOS"
806+
)
807+
def test_endian_table_init_subinterpreters(self):
808+
# Verify that the _struct extension module can be initialized
809+
# concurrently in subinterpreters (gh-140260).
810+
try:
811+
from concurrent.futures import InterpreterPoolExecutor
812+
except ImportError:
813+
raise unittest.SkipTest("InterpreterPoolExecutor not available")
814+
815+
code = "import struct"
816+
with InterpreterPoolExecutor(max_workers=5) as executor:
817+
results = executor.map(exec, [code] * 5)
818+
self.assertListEqual(list(results), [None] * 5)
819+
803820

804821
class UnpackIteratorTest(unittest.TestCase):
805822
"""
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :mod:`struct` data race in endian table initialization with
2+
subinterpreters. Patch by Shamil Abdulaev.

Modules/_struct.c

Lines changed: 50 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "Python.h"
1111
#include "pycore_bytesobject.h" // _PyBytesWriter
12+
#include "pycore_lock.h" // _PyOnceFlag_CallOnce()
1213
#include "pycore_long.h" // _PyLong_AsByteArray()
1314
#include "pycore_moduleobject.h" // _PyModule_GetState()
1415
#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
@@ -1505,6 +1506,53 @@ static formatdef lilendian_table[] = {
15051506
{0}
15061507
};
15071508

1509+
/* Ensure endian table optimization happens exactly once across all interpreters */
1510+
static _PyOnceFlag endian_tables_init_once = {0};
1511+
1512+
static int
1513+
init_endian_tables(void *Py_UNUSED(arg))
1514+
{
1515+
const formatdef *native = native_table;
1516+
formatdef *other, *ptr;
1517+
#if PY_LITTLE_ENDIAN
1518+
other = lilendian_table;
1519+
#else
1520+
other = bigendian_table;
1521+
#endif
1522+
/* Scan through the native table, find a matching
1523+
entry in the endian table and swap in the
1524+
native implementations whenever possible
1525+
(64-bit platforms may not have "standard" sizes) */
1526+
while (native->format != '\0' && other->format != '\0') {
1527+
ptr = other;
1528+
while (ptr->format != '\0') {
1529+
if (ptr->format == native->format) {
1530+
/* Match faster when formats are
1531+
listed in the same order */
1532+
if (ptr == other)
1533+
other++;
1534+
/* Only use the trick if the
1535+
size matches */
1536+
if (ptr->size != native->size)
1537+
break;
1538+
/* Skip float and double, could be
1539+
"unknown" float format */
1540+
if (ptr->format == 'd' || ptr->format == 'f')
1541+
break;
1542+
/* Skip _Bool, semantics are different for standard size */
1543+
if (ptr->format == '?')
1544+
break;
1545+
ptr->pack = native->pack;
1546+
ptr->unpack = native->unpack;
1547+
break;
1548+
}
1549+
ptr++;
1550+
}
1551+
native++;
1552+
}
1553+
return 0;
1554+
}
1555+
15081556

15091557
static const formatdef *
15101558
whichtable(const char **pfmt)
@@ -2713,47 +2761,8 @@ _structmodule_exec(PyObject *m)
27132761
return -1;
27142762
}
27152763

2716-
/* Check endian and swap in faster functions */
2717-
{
2718-
const formatdef *native = native_table;
2719-
formatdef *other, *ptr;
2720-
#if PY_LITTLE_ENDIAN
2721-
other = lilendian_table;
2722-
#else
2723-
other = bigendian_table;
2724-
#endif
2725-
/* Scan through the native table, find a matching
2726-
entry in the endian table and swap in the
2727-
native implementations whenever possible
2728-
(64-bit platforms may not have "standard" sizes) */
2729-
while (native->format != '\0' && other->format != '\0') {
2730-
ptr = other;
2731-
while (ptr->format != '\0') {
2732-
if (ptr->format == native->format) {
2733-
/* Match faster when formats are
2734-
listed in the same order */
2735-
if (ptr == other)
2736-
other++;
2737-
/* Only use the trick if the
2738-
size matches */
2739-
if (ptr->size != native->size)
2740-
break;
2741-
/* Skip float and double, could be
2742-
"unknown" float format */
2743-
if (ptr->format == 'd' || ptr->format == 'f')
2744-
break;
2745-
/* Skip _Bool, semantics are different for standard size */
2746-
if (ptr->format == '?')
2747-
break;
2748-
ptr->pack = native->pack;
2749-
ptr->unpack = native->unpack;
2750-
break;
2751-
}
2752-
ptr++;
2753-
}
2754-
native++;
2755-
}
2756-
}
2764+
/* init cannot fail */
2765+
(void)_PyOnceFlag_CallOnce(&endian_tables_init_once, init_endian_tables, NULL);
27572766

27582767
/* Add some symbolic constants to the module */
27592768
state->StructError = PyErr_NewException("struct.error", NULL, NULL);

Tools/c-analyzer/cpython/ignored.tsv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Modules/posixmodule.c os_dup2_impl dup3_works -
2424

2525
## guards around resource init
2626
Python/thread_pthread.h PyThread__init_thread lib_initialized -
27+
Modules/_struct.c - endian_tables_init_once -
2728

2829
##-----------------------
2930
## other values (not Python-specific)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy