txn_opts_cleanup is called from the following places:
- _mongoc_client_session_append_txn when the state is COMMITTED, COMMITTED_EMPTY, or ABORTED. The state will be reset to NONE and the options reset.
- mongoc_client_session_destroy, when the session itself is freed
txn_opts_set is called from the following places:
- _mongoc_client_session_new when creating a new client session. Opts are set first from the client and then from explicit default options (if any) passed to start_session
- mongoc_client_session_start_transaction() when starting a transaction. Opts are first set from the session's default options and then from explicit opts (if any) passed to start_transaction
txn_opts_set only assigns RC, WC, and RP if they are non-null. max_commit_time_ms is only assigned if it is not DEFAULT_MAX_COMMIT_TIME_MS, which is defined as zero. Since memory is zero-allocated, the initial options struct is correctly initialized with the default value for max_commit_time_ms.
Since txn_opts_cleanup never resets max_commit_time_ms, I think it's possible for one transaction's max_commit_time_ms to bleed over to the next. Consider a case where one transaction specifies a non-zero max_commit_time_ms. That transaction ends (either committing or aborting). The next transaction starts and if the default transaction opts had no max_commit_time_ms (i.e. the default), txn_opts_set will leave the field as-is. I believe the correct fix for this is to have txn_opts_cleanup also reset max_commit_time_ms as it does the RC, WC, and RP pointers. It shouldn't be too hard to create a regression test for this as well.