Skip to content

SIGSEGV in libmsodbcsql during process teardown (iconv_close) on macOS arm64 with concurrent encrypted connections #685

Description

@sdebruyn

Summary

On macOS arm64, the process crashes with SIGSEGV during interpreter/process teardown (exit()__cxa_finalize_ranges), inside the driver's static destructor calling iconv_close. The crash surfaces at shutdown when multiple worker threads have been using encrypted connections (Encrypt=yes) concurrently. The process terminates with exit code 139 and no Python traceback.

This appears related to, but distinct from, #668 (TLS stream corruption on concurrent encrypted reads — data corruption, no crash) and #679 (SIGSEGV in SQLFetchScroll during concurrent fetchmany). Here the faulting frame is not SQLFetchScroll but the driver's teardown path via libiconv.

Environment

  • macOS 26.5.2 (build 25F84), Apple Silicon (arm64)
  • Python 3.12.11
  • mssql-python 1.11.0 (bundled libmsodbcsql.18.dylib, mssql_python/libs/macos/arm64)
  • SQLAlchemy 2.1.0b3
  • Connection options: Encrypt=yes, TrustServerCertificate=yes, SNAPSHOT isolation
  • Concurrency: multiple worker threads. mssql-python's native connection pooling is enabled (enable_pooling=True), which uses a process-global pooling manager, so encrypted connections are pooled and reused across the process rather than being one-per-thread.

Crash

Signal: SIGSEGV / EXC_BAD_ACCESS (KERN_INVALID_ADDRESS), subtype "possible pointer authentication failure" at a wild address.

Faulting thread (from the macOS .ips crash report):

libiconv.2.dylib       _citrus_iconv_close
libiconv.2.dylib       __bsd_iconv_close
libmsodbcsql.18.dylib  <driver frame>
libsystem_c.dylib      __cxa_finalize_ranges
libsystem_c.dylib      exit
libdyld.dylib          dyld4::LibSystemHelpers::exit(int) const
dyld                   dyld4::LibSystemHelpersWrapper::exit(int) const
dyld                   start

So the crash happens while the process is exiting: exit() runs C++ static destructors (__cxa_finalize_ranges), one of which belongs to libmsodbcsql.18.dylib and calls iconv_close on what looks like an already-freed or corrupted iconv handle, producing a pointer-authentication failure.

Scenario

  1. Several worker threads read from different tables concurrently under SNAPSHOT isolation over pooled encrypted connections (Encrypt=yes).
  2. The application begins shutting down (an unrelated application-level error triggers a fail-fast exit()) while those threads/connections are still being torn down.
  3. During exit(), the driver's static-destructor cleanup segfaults in iconv_close.

The iconv involvement is notable: iconv is the character-encoding conversion layer, and #668 reports TLS/stream corruption specifically under concurrent encrypted reads on arm64. A corrupted iconv handle that only faults at driver finalization is consistent with encoding/stream state being left in a bad state under that same concurrency.

Relation to existing issues

This report is a third manifestation on the same platform and connection profile (macOS arm64, Encrypt=yes, concurrent threaded reads), but the crash occurs at process teardown via libiconv, not during an active fetch. Filing separately so the teardown/iconv stack is tracked; it may share the root cause reported in #668.

Notes

  • No Python-level exception is raised for the crash itself; only the exit code (139) and the macOS crash report indicate it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage neededFor new issues, not triaged yet.

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions