This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [v3] libstdc++/46455 - fix mutex and condvar leaks


On 18 November 2010 02:42, Jonathan Wakely wrote:
> This change adds destructors to the mutex types in the library, it's
> not trivial and could do with more testing on platforms where thread
> model != posix. ?I hacked the gthr headers to reproduce leaks under
> valgrind and think I've tested all the code paths, but I don't have
> anything suitable to add to the testsuite.

Attached is a modified gthr header I've been testing with, it might
prove useful to someone else one day.  Save this as
$foo/bits/gthr-default.h then compile with -I$foo to turn un-destroyed
mutexes into memory leaks, easily detected by valgrind. Use -DWINSTYLE
to exercise the win32 case.
/* Threads compatibility routines for libgcc2 and libobjc.  */
/* Compile this one with gcc.  */

/* Copyright (C) 2010 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.

You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
<http://www.gnu.org/licenses/>.  */

#ifndef GCC_GTHR_JWTEST_H
#define GCC_GTHR_JWTEST_H
// prevent real file from being included
#define GCC_GTHR_POSIX_H

#define __GTHREADS 1

#include <pthread.h>
#undef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
#undef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
#include <malloc.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct timespec __gthread_time_t;

typedef pthread_key_t __gthread_key_t;

typedef pthread_once_t __gthread_once_t;

struct __gthread_mutex_t {
  long counter;
  void *sema;
};

static inline pthread_mutex_t* get(__gthread_mutex_t* m)
{ return (pthread_mutex_t*)m->sema; }

#ifdef WINSTYLE
struct __gthread_recursive_mutex_t {
  long counter;
  long depth;
  unsigned long owner;
  void *sema;
};
static inline pthread_mutex_t* getr(__gthread_recursive_mutex_t* m)
{ return (pthread_mutex_t*)m->sema; }

#else /* ! WINSTYLE */

struct __gthread_recursive_mutex_t {
  __gthread_mutex_t actual;
};
static inline pthread_mutex_t* getr(__gthread_recursive_mutex_t* m)
{ return get(&m->actual); }

#endif /* !WINSTYLE */

#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION \
  __gthread_recursive_mutex_init_function

static inline int
__gthread_active_p (void)
{
  return 1;
}

static inline int
__gthread_once (__gthread_once_t *__once, void (*__func) (void))
{
  return pthread_once(__once, __func);
}

static inline int
__gthread_key_create (__gthread_key_t *__key,
		      void (*__dtor) (void *) )
{
  return pthread_key_create(__key, __dtor);
}

static inline int
__gthread_key_delete (__gthread_key_t __key)
{
  return pthread_key_delete(__key);
}

static inline void *
__gthread_getspecific (__gthread_key_t __key)
{
  return pthread_getspecific(__key);
}

static inline int
__gthread_setspecific (__gthread_key_t __key, const void *__ptr)
{
  return pthread_setspecific(__key, __ptr);
}

static inline void
__gthread_mutex_init_function (__gthread_mutex_t *__mutex)
{
  __mutex->counter = -1;
  __mutex->sema = malloc(sizeof(pthread_mutex_t));
  pthread_mutex_init(get(__mutex), NULL);
}

static inline void
__gthread_mutex_destroy (__gthread_mutex_t *__mutex)
{
  pthread_mutex_destroy(get(__mutex));
  free(__mutex->sema);
}

static inline int
__gthread_mutex_lock (__gthread_mutex_t *__mutex)
{
  if (__gthread_active_p ())
    return pthread_mutex_lock (get(__mutex));
  else
    return 0;
}

static inline int
__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
{
  if (__gthread_active_p ())
    return pthread_mutex_trylock (get(__mutex));
  else
    return 0;
}

static inline int
__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
{
  if (__gthread_active_p ())
    return pthread_mutex_unlock (get(__mutex));
  else
    return 0;
}

static inline void
__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
{
#ifdef WINSTYLE
  __mutex->counter = -1;
  __mutex->depth = 0;
  __mutex->owner = 0;
  __mutex->sema = malloc(sizeof(pthread_mutex_t));
#else
  __mutex->actual.counter = -1;
  __mutex->actual.sema = malloc(sizeof(pthread_mutex_t));
#endif
  pthread_mutexattr_t a;
  pthread_mutexattr_init(&a);
  pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE);
  pthread_mutex_init(getr(__mutex), &a);
  pthread_mutexattr_destroy(&a);
}

static inline int
__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
{
  if (__gthread_active_p ())
    return pthread_mutex_lock (getr(__mutex));
  else
    return 0;
}

static inline int
__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
{
  if (__gthread_active_p ())
    return pthread_mutex_trylock (getr(__mutex));
  else
    return 0;
}

static inline int
__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
{
  if (__gthread_active_p ())
    return pthread_mutex_unlock (getr(__mutex));
  else
    return 0;
}

static inline int
__gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
			   const __gthread_time_t *__abs_timeout)
{
  if (__gthread_active_p ())
    return pthread_mutex_timedlock (get(__mutex), __abs_timeout);
  else
    return 0;
}
static inline int
__gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
				     const __gthread_time_t *__abs_timeout)
{
  if (__gthread_active_p ())
    return pthread_mutex_timedlock (getr(__mutex), __abs_timeout);
  else
    return 0;
}



#ifdef __cplusplus
}
#endif

#endif /* ! GCC_GTHR_JWTEST_H */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]