mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-09 22:00:39 +01:00
add debug-only checking for thread safety
Lots of threads call the smsproto code now so the existing check was failing. Replace it with one that ensures that only one thread at a time is running the code. Debug-builds only.
This commit is contained in:
parent
2b87d60cba
commit
1e397d07f4
1 changed files with 39 additions and 26 deletions
|
@ -77,10 +77,39 @@ struct SMSProto {
|
||||||
|
|
||||||
int nFromPhones;
|
int nFromPhones;
|
||||||
FromPhoneRec* fromPhoneRecs;
|
FromPhoneRec* fromPhoneRecs;
|
||||||
|
#ifdef DEBUG
|
||||||
|
pthread_t starter;
|
||||||
|
int nestCount;
|
||||||
|
#endif
|
||||||
MPSLOT;
|
MPSLOT;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
# define CHECK_START( state ) { \
|
||||||
|
SMSProto* _state = state; \
|
||||||
|
pthread_t _self = pthread_self(); \
|
||||||
|
if ( _state->nestCount == 0 ) { \
|
||||||
|
XP_ASSERT( _state->starter == 0 ); \
|
||||||
|
_state->starter = _self; \
|
||||||
|
} else { \
|
||||||
|
XP_ASSERT( _state->starter == _self ); \
|
||||||
|
} \
|
||||||
|
++_state->nestCount; \
|
||||||
|
XP_LOGF( "%s(): check: %d", __func__, _state->nestCount ); \
|
||||||
|
|
||||||
|
# define CHECK_END() \
|
||||||
|
if ( --_state->nestCount == 0 ) { \
|
||||||
|
_state->starter = 0; \
|
||||||
|
} \
|
||||||
|
XP_LOGF( "%s(): check: %d", __func__, _state->nestCount ); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
# define CHECK_START(s)
|
||||||
|
# define CHECK_END()
|
||||||
|
#endif
|
||||||
|
|
||||||
#define KEY_PARTIALS PERSIST_KEY("partials")
|
#define KEY_PARTIALS PERSIST_KEY("partials")
|
||||||
#define KEY_NEXTID PERSIST_KEY("nextID")
|
#define KEY_NEXTID PERSIST_KEY("nextID")
|
||||||
|
|
||||||
|
@ -105,18 +134,12 @@ static void freeMsgIDRec( SMSProto* state, MsgIDRec* rec, int fromPhoneIndex,
|
||||||
static void freeForPhone( SMSProto* state, const XP_UCHAR* phone );
|
static void freeForPhone( SMSProto* state, const XP_UCHAR* phone );
|
||||||
static void freeMsg( SMSProto* state, MsgRec** msg );
|
static void freeMsg( SMSProto* state, MsgRec** msg );
|
||||||
static void freeRec( SMSProto* state, ToPhoneRec* rec );
|
static void freeRec( SMSProto* state, ToPhoneRec* rec );
|
||||||
#ifdef DEBUG
|
|
||||||
static void checkThread( SMSProto* state );
|
|
||||||
#else
|
|
||||||
# define checkThread(p)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SMSProto*
|
SMSProto*
|
||||||
smsproto_init( MPFORMAL XW_DUtilCtxt* dutil )
|
smsproto_init( MPFORMAL XW_DUtilCtxt* dutil )
|
||||||
{
|
{
|
||||||
SMSProto* state = (SMSProto*)XP_CALLOC( mpool, sizeof(*state) );
|
SMSProto* state = (SMSProto*)XP_CALLOC( mpool, sizeof(*state) );
|
||||||
state->dutil = dutil;
|
state->dutil = dutil;
|
||||||
// checkThread( state ); <-- Android's calling this on background thread now
|
|
||||||
MPASSIGN( state->mpool, mpool );
|
MPASSIGN( state->mpool, mpool );
|
||||||
|
|
||||||
XP_U16 siz = sizeof(state->nNextID);
|
XP_U16 siz = sizeof(state->nNextID);
|
||||||
|
@ -132,7 +155,6 @@ void
|
||||||
smsproto_free( SMSProto* state )
|
smsproto_free( SMSProto* state )
|
||||||
{
|
{
|
||||||
if ( NULL != state ) {
|
if ( NULL != state ) {
|
||||||
// checkThread( state ); <-- risky (see above)
|
|
||||||
XP_ASSERT( state->creator == 0 || state->creator == pthread_self() );
|
XP_ASSERT( state->creator == 0 || state->creator == pthread_self() );
|
||||||
|
|
||||||
for ( XP_U16 ii = 0; ii < state->nToPhones; ++ii ) {
|
for ( XP_U16 ii = 0; ii < state->nToPhones; ++ii ) {
|
||||||
|
@ -213,6 +235,7 @@ smsproto_prepOutbound( SMSProto* state, SMS_CMD cmd, XP_U32 gameID,
|
||||||
{
|
{
|
||||||
XP_USE( toPort );
|
XP_USE( toPort );
|
||||||
SMSMsgArray* result = NULL;
|
SMSMsgArray* result = NULL;
|
||||||
|
CHECK_START( state );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
XP_UCHAR* checksum = dutil_md5sum( state->dutil, buf, buflen );
|
XP_UCHAR* checksum = dutil_md5sum( state->dutil, buf, buflen );
|
||||||
|
@ -221,7 +244,6 @@ smsproto_prepOutbound( SMSProto* state, SMS_CMD cmd, XP_U32 gameID,
|
||||||
XP_FREEP( state->mpool, &checksum );
|
XP_FREEP( state->mpool, &checksum );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
checkThread( state );
|
|
||||||
ToPhoneRec* rec = getForPhone( state, toPhone, cmd != NONE );
|
ToPhoneRec* rec = getForPhone( state, toPhone, cmd != NONE );
|
||||||
|
|
||||||
/* First, add the new message (if present) to the array */
|
/* First, add the new message (if present) to the array */
|
||||||
|
@ -252,6 +274,7 @@ smsproto_prepOutbound( SMSProto* state, SMS_CMD cmd, XP_U32 gameID,
|
||||||
|
|
||||||
XP_LOGF( "%s() => %p (len=%d, *waitSecs=%d)", __func__, result,
|
XP_LOGF( "%s() => %p (len=%d, *waitSecs=%d)", __func__, result,
|
||||||
!!result ? result->nMsgs : 0, *waitSecsP );
|
!!result ? result->nMsgs : 0, *waitSecsP );
|
||||||
|
CHECK_END();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,12 +315,12 @@ smsproto_prepInbound( SMSProto* state, const XP_UCHAR* fromPhone,
|
||||||
XP_U16 wantPort, const XP_U8* data, XP_U16 len )
|
XP_U16 wantPort, const XP_U8* data, XP_U16 len )
|
||||||
{
|
{
|
||||||
XP_LOGF( "%s(): len=%d, fromPhone=%s", __func__, len, fromPhone );
|
XP_LOGF( "%s(): len=%d, fromPhone=%s", __func__, len, fromPhone );
|
||||||
checkThread( state );
|
SMSMsgArray* result = NULL;
|
||||||
|
CHECK_START( state );
|
||||||
|
|
||||||
XWStreamCtxt* stream = mkStream( state );
|
XWStreamCtxt* stream = mkStream( state );
|
||||||
stream_putBytes( stream, data, len );
|
stream_putBytes( stream, data, len );
|
||||||
|
|
||||||
SMSMsgArray* result = NULL;
|
|
||||||
XP_U8 proto;
|
XP_U8 proto;
|
||||||
if ( stream_gotU8( stream, &proto ) ) {
|
if ( stream_gotU8( stream, &proto ) ) {
|
||||||
switch ( proto ) {
|
switch ( proto ) {
|
||||||
|
@ -361,13 +384,14 @@ smsproto_prepInbound( SMSProto* state, const XP_UCHAR* fromPhone,
|
||||||
stream_destroy( stream );
|
stream_destroy( stream );
|
||||||
|
|
||||||
XP_LOGF( "%s() => %p (len=%d)", __func__, result, (!!result) ? result->nMsgs : 0 );
|
XP_LOGF( "%s() => %p (len=%d)", __func__, result, (!!result) ? result->nMsgs : 0 );
|
||||||
|
CHECK_END();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
smsproto_freeMsgArray( SMSProto* state, SMSMsgArray* arr )
|
smsproto_freeMsgArray( SMSProto* state, SMSMsgArray* arr )
|
||||||
{
|
{
|
||||||
checkThread( state );
|
CHECK_START( state );
|
||||||
|
|
||||||
for ( int ii = 0; ii < arr->nMsgs; ++ii ) {
|
for ( int ii = 0; ii < arr->nMsgs; ++ii ) {
|
||||||
XP_U8** ptr = arr->format == FORMAT_LOC
|
XP_U8** ptr = arr->format == FORMAT_LOC
|
||||||
|
@ -389,6 +413,7 @@ smsproto_freeMsgArray( SMSProto* state, SMSMsgArray* arr )
|
||||||
}
|
}
|
||||||
XP_FREEP( state->mpool, ptr );
|
XP_FREEP( state->mpool, ptr );
|
||||||
XP_FREEP( state->mpool, &arr );
|
XP_FREEP( state->mpool, &arr );
|
||||||
|
CHECK_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -620,7 +645,7 @@ freeMsgIDRec( SMSProto* state, MsgIDRec* rec, int fromPhoneIndex, int msgIDIndex
|
||||||
static void
|
static void
|
||||||
savePartials( SMSProto* state )
|
savePartials( SMSProto* state )
|
||||||
{
|
{
|
||||||
checkThread( state );
|
CHECK_START( state );
|
||||||
|
|
||||||
XWStreamCtxt* stream = mkStream( state );
|
XWStreamCtxt* stream = mkStream( state );
|
||||||
stream_putU8( stream, PARTIALS_FORMAT );
|
stream_putU8( stream, PARTIALS_FORMAT );
|
||||||
|
@ -655,6 +680,7 @@ savePartials( SMSProto* state )
|
||||||
stream_destroy( stream );
|
stream_destroy( stream );
|
||||||
|
|
||||||
LOG_RETURN_VOID();
|
LOG_RETURN_VOID();
|
||||||
|
CHECK_END();
|
||||||
} /* savePartials */
|
} /* savePartials */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -840,19 +866,6 @@ mkStream( SMSProto* state )
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static void
|
|
||||||
checkThread( SMSProto* state )
|
|
||||||
{
|
|
||||||
pthread_t curThread = pthread_self();
|
|
||||||
if ( 0 == state->creator ) {
|
|
||||||
state->creator = curThread;
|
|
||||||
} else {
|
|
||||||
/* If this is firing will need to use a mutex to make SMSProto access
|
|
||||||
thread-safe */
|
|
||||||
XP_ASSERT( state->creator == curThread );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
smsproto_runTests( MPFORMAL XW_DUtilCtxt* dutil )
|
smsproto_runTests( MPFORMAL XW_DUtilCtxt* dutil )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue