Skip to content

Python segfault during shutdown after exceptions #254

@bewithgaurav

Description

@bewithgaurav

Describe the bug

Python segmentation fault occurs during interpreter shutdown when failed cursor operations are encountered. The crash happens when C++ destructors in the native extension try to call ODBC driver functions and Python logging APIs after Python has begun shutting down, causing invalid memory access and segfaults.

Exception details:

EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000010
Termination Reason: Namespace SIGNAL, Code 11 Segmentation fault: 11

Key stack trace elements:
...
2   ddbc_bindings.cp313-universal2.so    SqlHandle::free() + 232
...
13  Python                               gc_collect_main + 2272
14  Python                               finalize_modules + 3048
15  Python                               _Py_Finalize + 936

To reproduce

Include a complete code listing (or project/solution) that we can run to reproduce the issue.

cursor = conn.cursor()
cursor.execute("syntax error") #Segfault happens here itself

row = cursor.fetchall()
print(row)

Expected behavior

The script should execute, catch the failed cursor operation, clean up resources properly, and exit without any segmentation fault. Python should shut down cleanly even after cursor operation failures occur.

Further technical details

Python version: 3.13
SQL Server version: SQL Server (any version with ODBC driver 18)
Operating system: macOS 14.7.1 (also reproducible on Linux)

Additional context

Root Cause Analysis:
The segmentation fault occurs during Python interpreter shutdown due to improper cleanup ordering:

  1. Python Shutdown Ordering: During Py_Finalize(), Python's garbage collector runs and finalizes C++ objects
  2. Invalid Driver State: The ODBC driver library may be unloaded or become invalid during shutdown
  3. Python API Corruption: sys.meta_path becomes None during finalization, breaking import mechanisms
  4. Destructor Calls: C++ destructors (SqlHandle::free() and LOG() function) try to call Python APIs and ODBC functions after Python has begun shutting down

Technical Details:

  • Crash occurs in SqlHandle::free() when calling SQLFreeHandle_ptr()
  • Also affects LOG() function which tries to import Python modules during shutdown
  • The issue manifests as EXC_BAD_ACCESS at memory address 0x0000000000000010
  • Crash is triggered by failed cursor operations (SQL syntax errors, execution failures, etc.) that create objects requiring cleanup during interpreter shutdown

Workaround: Currently no reliable workaround exists, as the crash occurs during normal Python shutdown after any failed cursor operation.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingtriage doneIssues that are triaged by dev team and are in investigation.

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions