Memory leak detection bugfixes for multi-threading.
This commit is contained in:
parent
0f8631495d
commit
934397ec66
13
CHANGES
13
CHANGES
@ -3,6 +3,19 @@
|
|||||||
|
|
||||||
Changes between 0.9.6 and 0.9.7 [xx XXX 2000]
|
Changes between 0.9.6 and 0.9.7 [xx XXX 2000]
|
||||||
|
|
||||||
|
*) Avoid false positives in memory leak detection code (crypto/mem_dbg.c)
|
||||||
|
due to incorrect handling of multi-threading:
|
||||||
|
|
||||||
|
1. Fix timing glitch in the MemCheck_off() portion of CRYPTO_mem_ctrl().
|
||||||
|
|
||||||
|
2. Fix logical glitch in is_MemCheck_on() aka CRYPTO_is_mem_check_on().
|
||||||
|
|
||||||
|
3. Count how many times MemCheck_off() has been called so that
|
||||||
|
nested use can be treated correctly. This also avoids
|
||||||
|
inband-signalling in the previous code (which relied on the
|
||||||
|
assumption that thread ID 0 is impossible).
|
||||||
|
[Bodo Moeller]
|
||||||
|
|
||||||
*) New options to 'ca' utility to support V2 CRL entry extensions.
|
*) New options to 'ca' utility to support V2 CRL entry extensions.
|
||||||
Currently CRL reason, invalidity date and hold instruction are
|
Currently CRL reason, invalidity date and hold instruction are
|
||||||
supported. Add new CRL extensions to V3 code and some new objects.
|
supported. Add new CRL extensions to V3 code and some new objects.
|
||||||
|
@ -81,7 +81,8 @@ static int mh_mode=CRYPTO_MEM_CHECK_OFF;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static unsigned long order = 0; /* number of memory requests */
|
static unsigned long order = 0; /* number of memory requests */
|
||||||
static LHASH *mh=NULL; /* hash-table of memory requests (address as key) */
|
static LHASH *mh=NULL; /* hash-table of memory requests (address as key);
|
||||||
|
* access requires MALLOC2 lock */
|
||||||
|
|
||||||
|
|
||||||
typedef struct app_mem_info_st
|
typedef struct app_mem_info_st
|
||||||
@ -103,7 +104,8 @@ typedef struct app_mem_info_st
|
|||||||
|
|
||||||
static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's
|
static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's
|
||||||
* that are at the top of their thread's stack
|
* that are at the top of their thread's stack
|
||||||
* (with `thread' as key) */
|
* (with `thread' as key);
|
||||||
|
* access requires MALLOC2 lock */
|
||||||
|
|
||||||
typedef struct mem_st
|
typedef struct mem_st
|
||||||
/* memory-block description */
|
/* memory-block description */
|
||||||
@ -128,7 +130,15 @@ static long options = /* extra information to be recorded */
|
|||||||
0;
|
0;
|
||||||
|
|
||||||
|
|
||||||
static unsigned long disabling_thread = 0;
|
static unsigned int num_disable = 0; /* num_disable > 0
|
||||||
|
* iff
|
||||||
|
* mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
|
||||||
|
*/
|
||||||
|
static unsigned long disabling_thread = 0; /* Valid iff num_disable > 0.
|
||||||
|
* CRYPTO_LOCK_MALLOC2 is locked
|
||||||
|
* exactly in this case (by the
|
||||||
|
* thread named in disabling_thread).
|
||||||
|
*/
|
||||||
|
|
||||||
int CRYPTO_mem_ctrl(int mode)
|
int CRYPTO_mem_ctrl(int mode)
|
||||||
{
|
{
|
||||||
@ -137,22 +147,23 @@ int CRYPTO_mem_ctrl(int mode)
|
|||||||
CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
|
CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
/* for applications: */
|
/* for applications (not to be called while multiple threads
|
||||||
|
* use the library): */
|
||||||
case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
|
case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
|
||||||
mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
|
mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
|
||||||
disabling_thread = 0;
|
num_disable = 0;
|
||||||
break;
|
break;
|
||||||
case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
|
case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
|
||||||
mh_mode = 0;
|
mh_mode = 0;
|
||||||
disabling_thread = 0;
|
num_disable = 0; /* should be true *before* MemCheck_stop is used,
|
||||||
|
or there'll be a lot of confusion */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* switch off temporarily (for library-internal use): */
|
/* switch off temporarily (for library-internal use): */
|
||||||
case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
|
case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
|
||||||
if (mh_mode & CRYPTO_MEM_CHECK_ON)
|
if (mh_mode & CRYPTO_MEM_CHECK_ON)
|
||||||
{
|
{
|
||||||
mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE;
|
if (!num_disable || (disabling_thread != CRYPTO_thread_id())) /* otherwise we already have the MALLOC2 lock */
|
||||||
if (disabling_thread != CRYPTO_thread_id()) /* otherwise we already have the MALLOC2 lock */
|
|
||||||
{
|
{
|
||||||
/* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
|
/* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
|
||||||
* we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
|
* we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
|
||||||
@ -169,20 +180,25 @@ int CRYPTO_mem_ctrl(int mode)
|
|||||||
* OpenSSL threads. */
|
* OpenSSL threads. */
|
||||||
CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
|
CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
|
||||||
CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
|
CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
|
||||||
|
mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
|
||||||
disabling_thread=CRYPTO_thread_id();
|
disabling_thread=CRYPTO_thread_id();
|
||||||
}
|
}
|
||||||
|
num_disable++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
|
case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
|
||||||
if (mh_mode & CRYPTO_MEM_CHECK_ON)
|
if (mh_mode & CRYPTO_MEM_CHECK_ON)
|
||||||
{
|
{
|
||||||
mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
|
if (num_disable) /* always true, or something is going wrong */
|
||||||
if (disabling_thread != 0)
|
|
||||||
{
|
{
|
||||||
disabling_thread=0;
|
num_disable--;
|
||||||
|
if (num_disable == 0)
|
||||||
|
{
|
||||||
|
mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
|
||||||
CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
|
CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -198,12 +214,12 @@ int CRYPTO_is_mem_check_on(void)
|
|||||||
|
|
||||||
if (mh_mode & CRYPTO_MEM_CHECK_ON)
|
if (mh_mode & CRYPTO_MEM_CHECK_ON)
|
||||||
{
|
{
|
||||||
CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
|
CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
|
||||||
|
|
||||||
ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
|
ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
|
||||||
&& disabling_thread != CRYPTO_thread_id();
|
|| (disabling_thread != CRYPTO_thread_id());
|
||||||
|
|
||||||
CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
|
CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
|
||||||
}
|
}
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
@ -299,7 +315,7 @@ int CRYPTO_push_info_(const char *info, const char *file, int line)
|
|||||||
|
|
||||||
if (is_MemCheck_on())
|
if (is_MemCheck_on())
|
||||||
{
|
{
|
||||||
MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
|
MemCheck_off(); /* obtain MALLOC2 lock */
|
||||||
|
|
||||||
if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
|
if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
|
||||||
{
|
{
|
||||||
@ -336,7 +352,7 @@ int CRYPTO_push_info_(const char *info, const char *file, int line)
|
|||||||
ami->next=amim;
|
ami->next=amim;
|
||||||
}
|
}
|
||||||
err:
|
err:
|
||||||
MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
|
MemCheck_on(); /* release MALLOC2 lock */
|
||||||
}
|
}
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
@ -348,11 +364,11 @@ int CRYPTO_pop_info(void)
|
|||||||
|
|
||||||
if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
|
if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
|
||||||
{
|
{
|
||||||
MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
|
MemCheck_off(); /* obtain MALLOC2 lock */
|
||||||
|
|
||||||
ret=(pop_info() != NULL);
|
ret=(pop_info() != NULL);
|
||||||
|
|
||||||
MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
|
MemCheck_on(); /* release MALLOC2 lock */
|
||||||
}
|
}
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
@ -363,12 +379,12 @@ int CRYPTO_remove_all_info(void)
|
|||||||
|
|
||||||
if (is_MemCheck_on()) /* _must_ be true */
|
if (is_MemCheck_on()) /* _must_ be true */
|
||||||
{
|
{
|
||||||
MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
|
MemCheck_off(); /* obtain MALLOC2 lock */
|
||||||
|
|
||||||
while(pop_info() != NULL)
|
while(pop_info() != NULL)
|
||||||
ret++;
|
ret++;
|
||||||
|
|
||||||
MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
|
MemCheck_on(); /* release MALLOC2 lock */
|
||||||
}
|
}
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
@ -391,11 +407,12 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
|
|||||||
|
|
||||||
if (is_MemCheck_on())
|
if (is_MemCheck_on())
|
||||||
{
|
{
|
||||||
MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
|
MemCheck_off(); /* make sure we hold MALLOC2 lock */
|
||||||
if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
|
if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
|
||||||
{
|
{
|
||||||
OPENSSL_free(addr);
|
OPENSSL_free(addr);
|
||||||
MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
|
MemCheck_on(); /* release MALLOC2 lock
|
||||||
|
* if num_disabled drops to 0 */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mh == NULL)
|
if (mh == NULL)
|
||||||
@ -454,7 +471,8 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
|
|||||||
OPENSSL_free(mm);
|
OPENSSL_free(mm);
|
||||||
}
|
}
|
||||||
err:
|
err:
|
||||||
MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
|
MemCheck_on(); /* release MALLOC2 lock
|
||||||
|
* if num_disabled drops to 0 */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -473,7 +491,7 @@ void CRYPTO_dbg_free(void *addr, int before_p)
|
|||||||
|
|
||||||
if (is_MemCheck_on() && (mh != NULL))
|
if (is_MemCheck_on() && (mh != NULL))
|
||||||
{
|
{
|
||||||
MemCheck_off();
|
MemCheck_off(); /* make sure we hold MALLOC2 lock */
|
||||||
|
|
||||||
m.addr=addr;
|
m.addr=addr;
|
||||||
mp=(MEM *)lh_delete(mh,(char *)&m);
|
mp=(MEM *)lh_delete(mh,(char *)&m);
|
||||||
@ -490,7 +508,8 @@ void CRYPTO_dbg_free(void *addr, int before_p)
|
|||||||
OPENSSL_free(mp);
|
OPENSSL_free(mp);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
|
MemCheck_on(); /* release MALLOC2 lock
|
||||||
|
* if num_disabled drops to 0 */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
@ -524,7 +543,7 @@ void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
|
|||||||
|
|
||||||
if (is_MemCheck_on())
|
if (is_MemCheck_on())
|
||||||
{
|
{
|
||||||
MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
|
MemCheck_off(); /* make sure we hold MALLOC2 lock */
|
||||||
|
|
||||||
m.addr=addr1;
|
m.addr=addr1;
|
||||||
mp=(MEM *)lh_delete(mh,(char *)&m);
|
mp=(MEM *)lh_delete(mh,(char *)&m);
|
||||||
@ -541,7 +560,8 @@ void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
|
|||||||
lh_insert(mh,(char *)mp);
|
lh_insert(mh,(char *)mp);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
|
MemCheck_on(); /* release MALLOC2 lock
|
||||||
|
* if num_disabled drops to 0 */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -650,10 +670,12 @@ void CRYPTO_mem_leaks(BIO *b)
|
|||||||
|
|
||||||
if (mh == NULL && amih == NULL)
|
if (mh == NULL && amih == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
MemCheck_off(); /* obtain MALLOC2 lock */
|
||||||
|
|
||||||
ml.bio=b;
|
ml.bio=b;
|
||||||
ml.bytes=0;
|
ml.bytes=0;
|
||||||
ml.chunks=0;
|
ml.chunks=0;
|
||||||
MemCheck_off(); /* obtains CRYPTO_LOCK_MALLOC2 */
|
|
||||||
if (mh != NULL)
|
if (mh != NULL)
|
||||||
lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak),
|
lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak),
|
||||||
(char *)&ml);
|
(char *)&ml);
|
||||||
@ -706,13 +728,7 @@ void CRYPTO_mem_leaks(BIO *b)
|
|||||||
mh_mode = old_mh_mode;
|
mh_mode = old_mh_mode;
|
||||||
CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
|
CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
|
||||||
}
|
}
|
||||||
MemCheck_on(); /* releases CRYPTO_LOCK_MALLOC2 */
|
MemCheck_on(); /* release MALLOC2 lock */
|
||||||
|
|
||||||
#if 0
|
|
||||||
lh_stats_bio(mh,b);
|
|
||||||
lh_node_stats_bio(mh,b);
|
|
||||||
lh_node_usage_stats_bio(mh,b);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_FP_API
|
#ifndef NO_FP_API
|
||||||
|
Loading…
x
Reference in New Issue
Block a user