After investigation into this, I discovered that there was a
race condition in TemporalFormat::match():
TemporalFormat::_re is the compiled PCRE regular expression object
inside each of the TemporalFormat objects, which are shared
among all threads and live in global scope.
Unfortunately, TemporalFormat::match() was using the member
variable TemporalFormat::_match_vector as its match state.
At high concurrency, this means that the following race
condition could happen:
Thread 1 executes pcre_exec() and finds a match, therefore
populating TemporalFormat::_match_vector of integers
with the position offsets of the matched pieces of the temporal object.
Thread 1, during construction of the Temporal output of
TemporalFormat::match(), uses these _match_vector position
offsets in calling std::string::substr on a copy of the
matched string, essentially "cutting up" the string
into year, month, day, etc.
Thread 2 executes pcre_exec() and also finds a match,
thereby changing TemporalFormat::_match_vector to something
different
Thread 1 continues trying to use std::string::substr(),
but now uses offsets that are invalid for its string,
thereby producing an out_of_range exception.
The solution is to pull the TemporalFormat::_match_vector
member variable and instead put a function-scope-level
match_vector variable on the stack inside TemporalFormat::match().
Fixes LP Bug #500031:
"dbt2 fails with 1024 connections"
After investigation into this, I discovered that there was a :match( ):
race condition in TemporalFormat:
TemporalFor mat::_re is the compiled PCRE regular expression object
inside each of the TemporalFormat objects, which are shared
among all threads and live in global scope.
Unfortunately, TemporalFormat: :match( ) was using the member :_match_ vector as its match state.
variable TemporalFormat:
At high concurrency, this means that the following race
condition could happen:
Thread 1 executes pcre_exec() and finds a match, therefore :_match_ vector of integers
populating TemporalFormat:
with the position offsets of the matched pieces of the temporal object.
Thread 1, during construction of the Temporal output of mat::match( ), uses these _match_vector position
TemporalFor
offsets in calling std::string::substr on a copy of the
matched string, essentially "cutting up" the string
into year, month, day, etc.
Thread 2 executes pcre_exec() and also finds a match, :_match_ vector to something
thereby changing TemporalFormat:
different
Thread 1 continues trying to use std::string: :substr( ),
but now uses offsets that are invalid for its string,
thereby producing an out_of_range exception.
The solution is to pull the TemporalFormat: :_match_ vector scope-level :match( ).
member variable and instead put a function-
match_vector variable on the stack inside TemporalFormat: