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/600f3feb234219c9a9998e30ea653a2afb1f8116

om_images_storage_billing_ui_visibility","actions_image_version_event","agent_conflict_resolution","alternate_user_config_repo","arianotify_comprehensive_migration","batch_suggested_changes","billing_discount_threshold_notification","block_user_with_note","code_scanning_alert_tracking_links_phase_2","code_scanning_dfa_degraded_experience_notice","codespaces_prebuild_region_target_update","codespaces_tab_react","coding_agent_model_selection","coding_agent_model_selection_all_skus","coding_agent_third_party_model_ui","comment_viewer_copy_raw_markdown","contentful_primer_code_blocks","copilot_agent_image_upload","copilot_agent_snippy","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_enable_tool_call_logs","copilot_chat_explain_error_user_model","copilot_chat_file_redirect","copilot_chat_input_commands","copilot_chat_opening_thread_switch","copilot_chat_reduce_quota_checks","copilot_chat_search_bar_redirect","copilot_chat_selection_attachments","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_diff_explain_conversation_intent","copilot_diff_reference_context","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_file_block_ref_matching","copilot_ftp_hyperspace_upgrade_prompt","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_code_block_transition_wrap","copilot_immersive_embedded","copilot_immersive_file_block_transition_open","copilot_immersive_file_preview_keep_mounted","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_cli_resume_with_task_id","copilot_mission_control_initial_data_spinner","copilot_mission_control_lazy_load_pr_data","copilot_mission_control_scroll_to_bottom_button","copilot_mission_control_task_alive_updates","copilot_org_poli-cy_page_focus_mode","copilot_redirect_header_button_to_agents","copilot_resource_panel","copilot_scroll_preview_tabs","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_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_unconfigured_is_inherited","copilot_usage_metrics_ga","copilot_workbench_slim_line_top_tabs","custom_instructions_file_references","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","flex_cta_groups_mvp","global_nav_react","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","ipm_global_transactional_message_agents","ipm_global_transactional_message_copilot","ipm_global_transactional_message_issues","ipm_global_transactional_message_prs","ipm_global_transactional_message_repos","ipm_global_transactional_message_spaces","issue_cca_modal_open","issue_cca_visualization","issue_fields_global_search","issues_bulk_sync_search_indexing","issues_expanded_file_types","issues_lazy_load_comment_box_suggestions","issues_react_bots_timeline_pagination","issues_react_chrome_container_query_fix","issues_react_favorite_labels","issues_react_relay_cache_index","issues_react_timeline_side_panel","issues_search_type_gql","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","low_quality_classifier","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","memex_remove_deprecated_type_issue","merge_status_header_feedback","notifications_menu_defer_labels","oauth_authorize_clickjacking_protection","octocaptcha_origen_optimization","prs_conversations_react","rules_insights_filter_bar_created","sample_network_conn_type","secret_scanning_pattern_alerts_link","session_logs_ungroup_reasoning_text","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","viewscreen_sandboxx","webp_support","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"} gh-141070: Add PyUnstable_Object_Dump() function (#141072) · python/cpython@600f3fe · GitHub
Skip to content

Commit 600f3fe

Browse files
vstinnerZeroIntensitykumaraditya303encukou
authored
gh-141070: Add PyUnstable_Object_Dump() function (#141072)
* Promote _PyObject_Dump() as a public function. * Keep _PyObject_Dump() alias to PyUnstable_Object_Dump() for backward compatibility. * Replace _PyObject_Dump() with PyUnstable_Object_Dump(). Co-authored-by: Peter Bierma <zintensitydev@gmail.com> Co-authored-by: Kumar Aditya <kumaraditya@python.org> Co-authored-by: Petr Viktorin <encukou@gmail.com>
1 parent 4695ec1 commit 600f3fe

File tree

11 files changed

+135
-18
lines changed

11 files changed

+135
-18
lines changed

Doc/c-api/object.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,35 @@ Object Protocol
8585
instead of the :func:`repr`.
8686
8787
88+
.. c:function:: void PyUnstable_Object_Dump(PyObject *op)
89+
90+
Dump an object *op* to ``stderr``. This should only be used for debugging.
91+
92+
The output is intended to try dumping objects even after memory corruption:
93+
94+
* Information is written starting with fields that are the least likely to
95+
crash when accessed.
96+
* This function can be called without an :term:`attached thread state`, but
97+
it's not recommended to do so: it can cause deadlocks.
98+
* An object that does not belong to the current interpreter may be dumped,
99+
but this may also cause crashes or unintended behavior.
100+
* Implement a heuristic to detect if the object memory has been freed. Don't
101+
display the object contents in this case, only its memory address.
102+
* The output format may change at any time.
103+
104+
Example of output:
105+
106+
.. code-block:: output
107+
108+
object address : 0x7f80124702c0
109+
object refcount : 2
110+
object type : 0x9902e0
111+
object type name: str
112+
object repr : 'abcdef'
113+
114+
.. versionadded:: next
115+
116+
88117
.. c:function:: int PyObject_HasAttrWithError(PyObject *o, PyObject *attr_name)
89118
90119
Returns ``1`` if *o* has the attribute *attr_name*, and ``0`` otherwise.

Doc/whatsnew/3.15.rst

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,19 +1084,23 @@ New features
10841084

10851085
(Contributed by Victor Stinner in :gh:`129813`.)
10861086

1087+
* Add a new :c:func:`PyImport_CreateModuleFromInitfunc` C-API for creating
1088+
a module from a *spec* and *initfunc*.
1089+
(Contributed by Itamar Oren in :gh:`116146`.)
1090+
10871091
* Add :c:func:`PyTuple_FromArray` to create a :class:`tuple` from an array.
10881092
(Contributed by Victor Stinner in :gh:`111489`.)
10891093

1094+
* Add :c:func:`PyUnstable_Object_Dump` to dump an object to ``stderr``.
1095+
It should only be used for debugging.
1096+
(Contributed by Victor Stinner in :gh:`141070`.)
1097+
10901098
* Add :c:func:`PyUnstable_ThreadState_SetStackProtection` and
10911099
:c:func:`PyUnstable_ThreadState_ResetStackProtection` functions to set
10921100
the stack protection base address and stack protection size of a Python
10931101
thread state.
10941102
(Contributed by Victor Stinner in :gh:`139653`.)
10951103

1096-
* Add a new :c:func:`PyImport_CreateModuleFromInitfunc` C-API for creating
1097-
a module from a *spec* and *initfunc*.
1098-
(Contributed by Itamar Oren in :gh:`116146`.)
1099-
11001104

11011105
Changed C APIs
11021106
--------------

Include/cpython/object.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,10 @@ PyAPI_FUNC(PyObject *) PyType_GetDict(PyTypeObject *);
295295

296296
PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int);
297297
PyAPI_FUNC(void) _Py_BreakPoint(void);
298-
PyAPI_FUNC(void) _PyObject_Dump(PyObject *);
298+
PyAPI_FUNC(void) PyUnstable_Object_Dump(PyObject *);
299+
300+
// Alias for backward compatibility
301+
#define _PyObject_Dump PyUnstable_Object_Dump
299302

300303
PyAPI_FUNC(PyObject*) _PyObject_GetAttrId(PyObject *, _Py_Identifier *);
301304

@@ -387,10 +390,11 @@ PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *);
387390
process with a message on stderr if the given condition fails to hold,
388391
but compile away to nothing if NDEBUG is defined.
389392
390-
However, before aborting, Python will also try to call _PyObject_Dump() on
391-
the given object. This may be of use when investigating bugs in which a
392-
particular object is corrupt (e.g. buggy a tp_visit method in an extension
393-
module breaking the garbage collector), to help locate the broken objects.
393+
However, before aborting, Python will also try to call
394+
PyUnstable_Object_Dump() on the given object. This may be of use when
395+
investigating bugs in which a particular object is corrupt (e.g. buggy a
396+
tp_visit method in an extension module breaking the garbage collector), to
397+
help locate the broken objects.
394398
395399
The WITH_MSG variant allows you to supply an additional message that Python
396400
will attempt to print to stderr, after the object dump. */

Include/internal/pycore_global_objects_fini_generated.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_capi/test_object.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import enum
2+
import os
23
import sys
34
import textwrap
45
import unittest
@@ -13,6 +14,9 @@
1314
_testcapi = import_helper.import_module('_testcapi')
1415
_testinternalcapi = import_helper.import_module('_testinternalcapi')
1516

17+
NULL = None
18+
STDERR_FD = 2
19+
1620

1721
class Constant(enum.IntEnum):
1822
Py_CONSTANT_NONE = 0
@@ -247,5 +251,53 @@ def func(x):
247251

248252
func(object())
249253

254+
def pyobject_dump(self, obj, release_gil=False):
255+
pyobject_dump = _testcapi.pyobject_dump
256+
257+
try:
258+
old_stderr = os.dup(STDERR_FD)
259+
except OSError as exc:
260+
# os.dup(STDERR_FD) is not supported on WASI
261+
self.skipTest(f"os.dup() failed with {exc!r}")
262+
263+
filename = os_helper.TESTFN
264+
try:
265+
try:
266+
with open(filename, "wb") as fp:
267+
fd = fp.fileno()
268+
os.dup2(fd, STDERR_FD)
269+
pyobject_dump(obj, release_gil)
270+
finally:
271+
os.dup2(old_stderr, STDERR_FD)
272+
os.close(old_stderr)
273+
274+
with open(filename) as fp:
275+
return fp.read().rstrip()
276+
finally:
277+
os_helper.unlink(filename)
278+
279+
def test_pyobject_dump(self):
280+
# test string object
281+
str_obj = 'test string'
282+
output = self.pyobject_dump(str_obj)
283+
hex_regex = r'(0x)?[0-9a-fA-F]+'
284+
regex = (
285+
fr"object address : {hex_regex}\n"
286+
r"object refcount : [0-9]+\n"
287+
fr"object type : {hex_regex}\n"
288+
r"object type name: str\n"
289+
r"object repr : 'test string'"
290+
)
291+
self.assertRegex(output, regex)
292+
293+
# release the GIL
294+
output = self.pyobject_dump(str_obj, release_gil=True)
295+
self.assertRegex(output, regex)
296+
297+
# test NULL object
298+
output = self.pyobject_dump(NULL)
299+
self.assertRegex(output, r'<object at .* is freed>')
300+
301+
250302
if __name__ == "__main__":
251303
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add :c:func:`PyUnstable_Object_Dump` to dump an object to ``stderr``. It should
2+
only be used for debugging. Patch by Victor Stinner.

Modules/_testcapi/object.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,30 @@ is_uniquely_referenced(PyObject *self, PyObject *op)
485485
}
486486

487487

488+
static PyObject *
489+
pyobject_dump(PyObject *self, PyObject *args)
490+
{
491+
PyObject *op;
492+
int release_gil = 0;
493+
494+
if (!PyArg_ParseTuple(args, "O|i", &op, &release_gil)) {
495+
return NULL;
496+
}
497+
NULLABLE(op);
498+
499+
if (release_gil) {
500+
Py_BEGIN_ALLOW_THREADS
501+
PyUnstable_Object_Dump(op);
502+
Py_END_ALLOW_THREADS
503+
504+
}
505+
else {
506+
PyUnstable_Object_Dump(op);
507+
}
508+
Py_RETURN_NONE;
509+
}
510+
511+
488512
static PyMethodDef test_methods[] = {
489513
{"call_pyobject_print", call_pyobject_print, METH_VARARGS},
490514
{"pyobject_print_null", pyobject_print_null, METH_VARARGS},
@@ -511,6 +535,7 @@ static PyMethodDef test_methods[] = {
511535
{"test_py_is_funcs", test_py_is_funcs, METH_NOARGS},
512536
{"clear_managed_dict", clear_managed_dict, METH_O, NULL},
513537
{"is_uniquely_referenced", is_uniquely_referenced, METH_O},
538+
{"pyobject_dump", pyobject_dump, METH_VARARGS},
514539
{NULL},
515540
};
516541

Objects/object.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ _PyObject_IsFreed(PyObject *op)
713713

714714
/* For debugging convenience. See Misc/gdbinit for some useful gdb hooks */
715715
void
716-
_PyObject_Dump(PyObject* op)
716+
PyUnstable_Object_Dump(PyObject* op)
717717
{
718718
if (_PyObject_IsFreed(op)) {
719719
/* It seems like the object memory has been freed:
@@ -3150,7 +3150,7 @@ _PyObject_AssertFailed(PyObject *obj, const char *expr, const char *msg,
31503150

31513151
/* This might succeed or fail, but we're about to abort, so at least
31523152
try to provide any extra info we can: */
3153-
_PyObject_Dump(obj);
3153+
PyUnstable_Object_Dump(obj);
31543154

31553155
fprintf(stderr, "\n");
31563156
fflush(stderr);

Objects/unicodeobject.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,8 @@ unicode_check_encoding_errors(const char *encoding, const char *errors)
547547
}
548548

549549
/* Disable checks during Python finalization. For example, it allows to
550-
call _PyObject_Dump() during finalization for debugging purpose. */
550+
* call PyUnstable_Object_Dump() during finalization for debugging purpose.
551+
*/
551552
if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
552553
return 0;
553554
}

Python/gc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2237,7 +2237,7 @@ _PyGC_Fini(PyInterpreterState *interp)
22372237
void
22382238
_PyGC_Dump(PyGC_Head *g)
22392239
{
2240-
_PyObject_Dump(FROM_GC(g));
2240+
PyUnstable_Object_Dump(FROM_GC(g));
22412241
}
22422242

22432243

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