[Gc] Re: pthread_cancel(3) confuses 'GC_suspend_all ()'

Boehm, Hans hans.boehm at hp.com
Tue Sep 22 18:36:01 PDT 2009


Thanks.  I merged both of those into my tree, and found another minor problem, in that the collector turned pthread_create into a cancellation point.  (Apparently a breakpoint in __pthread_unwind() can give some idea from gdb of where cancellations are delivered.  There should be a better way.)

After that, it looks to me like the test program has some issues that may hide other problems:

- cancellation and thread creation race, meaning that the number of threads can potentially get huge.

- my impression is that if cancellation isn't delivered while the thread is running, it isn't delivered at all.  This means late cancellations result in thread leaks, and you can get truly impressive proces sizes, with almost none of that in the GC heap.  I think this starts to look like a hang after a while.  Since the GC calls shouldn't be cancellation points, all of this is becoming more likely as I fix things.  (Detaching threads doesn't seem to work, since that seems to cause pthread_cancel to crash if it's too late.)

Here's my attempt at a revised patch and a better (and unfortunately probably less aggressive) test program.

Hans



> -----Original Message-----
> From: gc-bounces at napali.hpl.hp.com 
> [mailto:gc-bounces at napali.hpl.hp.com] On Behalf Of Ivan Maidanski
> Sent: Friday, September 18, 2009 4:30 AM
> To: gc at napali.hpl.hp.com
> Subject: Re[5]: [Gc] Re: pthread_cancel(3) confuses 
> 'GC_suspend_all ()'
> 
> Hi!
> 
> Today I wrote:
> > "Boehm, Hans" <hans.boehm at hp.com> wrote:
> > > Thanks for the careful proofreading.  I applied these to my tree.
> > > 
> > > Unfortunately, I think they don't explain Ludo's results. 
>  I'll need to do some testing/debugging before posting the 
> next version.
> > > 
> > > Hans
> > 
> > One more place (to make a bit better):
> > 
> > #   if defined(GC_ASSERTIONS) && \
> >        (defined(LINUX) || defined(HPUX) /* and probably 
> others ... */)
> > 
> > ->
> > 
> > #   if defined(GC_ASSERTIONS) && (defined(USE_COMPILER_TLS) \
> >        || (defined(LINUX) && !defined(ARM32) \
> >            && (__GNUC__ > 3 || (__GNUC__ == 3 && 
> __GNUC_MINOR__ >= 3)) \
> >        || defined(HPUX) /* and probably others ... */)
> 
> Also, in misc.c:
> 
>  #   if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS)
> -      if (!GC_is_initialized) {
>  #     ifndef MSWINCE
>          BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL;
>          HMODULE hK32 = GetModuleHandle(TEXT("kernel32.dll"));
> @@ -541,7 +546,6 @@
>          else
>  #     endif /* !MSWINCE */
>    	/* else */ InitializeCriticalSection (&GC_allocate_ml);
> -      }
>  #   endif /* GC_WIN32_THREADS */
> 
> Don't remove the braces {}.
> 
> 
> PS. Sorry for previous 2 duplicate posts (this seems to be 
> the problems in my mailing system).
> 
> Bye.
> _______________________________________________
> Gc mailing list
> Gc at linux.hpl.hp.com
> http://www.hpl.hp.com/hosted/linux/mail-archives/gc/
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cancel.patch
Type: application/octet-stream
Size: 16262 bytes
Desc: cancel.patch
Url : http://napali.hpl.hp.com/pipermail/gc/attachments/20090923/1d79d93c/cancel-0001.obj
-------------- next part --------------
#define GC_THREADS 1

#include <gc/gc.h>
#include <pthread.h>
#include <stdio.h>


static void *
small_allocator (void *arg)
{
  int i;

  printf (",");
  for (i = 0; i < 1000; ++i) {
     GC_MALLOC (11111);
     GC_MALLOC (16);
     GC_MALLOC (32);
  }

  return GC_MALLOC (11111);
}

static void *
thread_maker (void *arg)
{
  pthread_t t1, t2, t3;
  void * dummy;


  while(1) {
    pthread_create (&t1, NULL, small_allocator, NULL);
    pthread_create (&t2, NULL, small_allocator, NULL);
    pthread_create (&t3, NULL, small_allocator, NULL);
    printf (".");
    pthread_cancel (t1);
    pthread_cancel (t2);
    pthread_cancel (t3);
    GC_MALLOC (11111);
    GC_MALLOC (9999);
    pthread_join(t1, &dummy);
    pthread_join(t2, &dummy);
    pthread_join(t3, &dummy);
  }

  return GC_MALLOC (11111);
}

static void *
allocator (void *arg)
{
  while (1)
    {
      GC_MALLOC (12345);
      printf ("+");
    }

  return NULL;
}


int
main (int argc, char *argv[])
{
  pthread_t alloc, make;

  GC_INIT ();

  setvbuf (stdout, NULL, _IONBF, 0);

  pthread_create (&make, NULL, thread_maker, NULL);
  pthread_create (&alloc, NULL, allocator, NULL);

  while (1);

  return 0;
}


More information about the Gc mailing list