test_cMsgReaderKeepAlive

Regression test for issue #1433 (follow-up to #676 / #1432).

A Msg_C reader (e.g. a C module’s dataInMsg) that subscribes to a Python source stores raw pointers into that source’s memory. If the only Python reference to the source then goes out of scope, the source must not be garbage-collected while the subscription is live, otherwise the reader points into freed memory. The keep-alive added for #1433 retains the source owner and releases it again on unsubscribe(), on re-subscribe, when a stand-alone subscriber proxy is collected, and when the C module that embeds the subscriber is collected.

These tests assert the lifetime contract directly with weakref (deterministic, no reliance on memory being clobbered) and additionally check that a module reads the correct, live data end-to-end after a garbage-collection pass.

test_cMsgReaderKeepAlive.test_configEmbeddedSourceOwnerSurvivesGC()[source]

A wrapper reader retains the config that owns an embedded source.

test_cMsgReaderKeepAlive.test_configReaderKeepAliveTransfersToWrapper()[source]

A config reader transfers its active source keep-alive to its wrapper.

test_cMsgReaderKeepAlive.test_configSourceOwnerLeaseTransfersToWrapper()[source]

An existing source lease follows config storage into its new wrapper.

test_cMsgReaderKeepAlive.test_moduleDeathReleasesSources()[source]

When the owning C module is collected, its subscribed sources are released (no leak); this exercises the module-owned keep-alive dictionary.

test_cMsgReaderKeepAlive.test_moduleEmbeddedCMsgSourceOwnerSurvivesGC()[source]

A C module’s Msg_C reader keeps the owning module alive when subscribing to another module’s embedded Msg_C source.

test_cMsgReaderKeepAlive.test_moduleEmbeddedCMsgSourceSurvivesGC()[source]

A C module’s Msg_C reader keeps a stand-alone Msg_C source alive across GC.

test_cMsgReaderKeepAlive.test_moduleEmbeddedCppSourceSurvivesGC()[source]

A C module’s Msg_C reader keeps a C++ Message source alive across GC, and reads its live data end-to-end.

test_cMsgReaderKeepAlive.test_rawAddressResubscribeReleasesPreviousKeepAlive()[source]

Re-subscribing by raw integer address releases any previous Python source.

test_cMsgReaderKeepAlive.test_rawAddressSubscriptionStillWorks()[source]

Subscribing by raw integer address must keep working: that path has no Python source object to retain (the caller owns the source’s lifetime), so the keep-alive layer must simply stay out of its way.

test_cMsgReaderKeepAlive.test_resubscribeReplacesKeepAlive()[source]

Re-subscribing releases the previous source and retains the new one.

test_cMsgReaderKeepAlive.test_resubscribeToEmbeddedSourcePreservesOwner()[source]

Re-subscribing through a non-owning Msg_C proxy preserves its owner.

test_cMsgReaderKeepAlive.test_resubscribeWeakrefCallbackCanUnsubscribe()[source]

A source weakref callback can safely unsubscribe during re-subscription.

test_cMsgReaderKeepAlive.test_standaloneSubscriberSurvivesGCAndReleasesOnDeath()[source]

A stand-alone Msg_C subscriber keeps its source alive, reads it correctly, and releases it when the subscriber itself is collected.

test_cMsgReaderKeepAlive.test_unsubscribeReleasesKeepAlive()[source]

unsubscribe() drops the keep-alive so the source can be collected.

test_cMsgReaderKeepAlive.test_unsubscribeWeakrefCallbackCanResubscribe()[source]

A source weakref callback can safely reconnect an unsubscribing reader.