wu :: forums (http://www.ocf.berkeley.edu/~wwu/cgi-bin/yabb/YaBB.cgi)
riddles >> cs >> bug in fprintf??
(Message started by: gowrikumar on Nov 5th, 2007, 2:15am)

Title: bug in fprintf??
Post by gowrikumar on Nov 5th, 2007, 2:15am
Hi all,
Last week, I had received a bug, whose description was as follows:
The program was creating a pthread. but before creating it, the thread stack size is set to minimum size possible. And then in the thread, fprintf is called. When o/p is written to stdout, there ``doesn't seem'' to be an issue. But when the ouput is being written to stderr, the code segfaults.


Code:
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>

#define THREAD_STACK_SIZE PTHREAD_STACK_MIN

void* Hello(void *ptr)
{
   char *newptr;
   fprintf(stderr,"%s"," Hello World!\n");
   return newptr;
}

int main()
{
   int error;
   pthread_t id;
   pthread_attr_t  attr;
   char *ptr;
   size_t size;
   int stack_size;

   ptr = (char *)calloc(5,sizeof(char));

   error = pthread_attr_init(&attr);
   pthread_attr_getstacksize(&attr,&size);
   printf("Initial  stack size is : %d\n",size);

   stack_size = THREAD_STACK_SIZE;
   if (stack_size < PTHREAD_STACK_MIN) {
       stack_size = PTHREAD_STACK_MIN;
   }
   if ((error=pthread_attr_setstacksize(&attr, stack_size)) != 0)
   {
       printf("\n error number is : %d \n",error);
       return -1;
   }
   pthread_attr_getstacksize(&attr,&size);
   printf("After resizing the stack size is : %d\n",size);
   error = pthread_create(&id,&attr,Hello,ptr);
   sleep(10);
   return 0;

}


$gcc -Wall fprintf.c -lpthread
$ ./a.out
Initial  stack size is : 10485760
After resizing the stack size is : 16384
Segmentation fault

How would you solve this bug (and support yourself that your solution is correct)?

Regards,
Gowri Kumar

Title: Re: bug in fprintf??
Post by towr on Nov 5th, 2007, 2:27am
I've run the program a dozen time, just the way as you posted it, and never got an error.

compiler version: gcc (GCC) 4.1.2 20070925

Title: Re: bug in fprintf??
Post by gowrikumar on Nov 5th, 2007, 2:34am

on 11/05/07 at 02:27:13, towr wrote:
I've run the program a dozen time as you posted it, and never got an error.

compiler version: gcc (GCC) 4.1.2 20070925

Hmm!! that makes the problem a bit more intersting :-)

These are machines I have tried on:
<snip>
-bash-2.05b$ uname -a
Linux ...... 2.4.21-37.ELsmp #1 SMP Wed Sep 7 13:24:00 EDT 2005 i686 athlon i386 GNU/Linux
-bash-2.05b$ gcc --version
gcc (GCC) 3.4.3 (TWW)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ uname -a
Linux gpmv36 ..... 2.6.9-55.0.2.ELsmp #1 SMP Tue Jun 26 14:30:58 EDT 2007 i686 i686 i386 GNU/Linux
$ gcc --version
gcc (GCC) 3.4.6 20060404 (Red Hat 3.4.6-8)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
</snip>

Regards,
Gowri Kumar

Title: Re: bug in fprintf??
Post by towr on Nov 5th, 2007, 2:53am
(For completeness, the machine I compiled it on:
Linux .... 2.6.22.9-91.fc7 #1 SMP Thu Sep 27 23:10:59 EDT 2007 i686 i686 i386 GNU/Linux)


So it seems the difference might be due to you using an older version of GCC. I rather doubt fprintf changed any during that time, though.

What happens if you don't resize the stack, does it work then?
Although, I also get the exact same stack size, so that can't really be the problem either.

Title: Re: bug in fprintf??
Post by gowrikumar on Nov 5th, 2007, 3:08am

on 11/05/07 at 02:53:49, towr wrote:
(For completeness, the machine I compiled it on:
Linux .... 2.6.22.9-91.fc7 #1 SMP Thu Sep 27 23:10:59 EDT 2007 i686 i686 i386 GNU/Linux)

So it seems the difference might be due to you using an older version of GCC. I rather doubt fprintf changed any during that time, though.

What happens if you don't resize the stack, does it work then?
Although, I also get the exact same stack size, so that can't really be the problem either.

It seems to work (on my machine), if the stack is not resized. It also seem to work if the stack size is kept at around 22K.

Yes, I ruled out bug being in fprintf. It's very very rare.

Regards,
Gowri Kumar

Title: Re: bug in fprintf??
Post by Aryabhatta on Nov 5th, 2007, 12:44pm
It seems like the bug is the return newptr in the Hello function.

According to doc (don't know which one) for pthread_create, the value returned by start routine (in this case Hello) is used by pthread_exit. And in case the ptr refers to a local var of the exiting thread, the behavior is undefined and is an error to do that.

Title: Re: bug in fprintf??
Post by gowrikumar on Nov 18th, 2007, 11:04pm
It turned out to be that the stack size allocated for the thread is very small. To prove that it is stack size, a signal handler for the SIGSEGV is installed. The signal handler is set to be run on the alternate signal stack (to handle the stack overflow problem).


The code (fprint.c) is attached with this post (instead of inline)

Title: Re: bug in fprintf??
Post by gowrikumar on Nov 18th, 2007, 11:11pm
Looks like, some problem with attachment!!

Code:
#include <sys/signal.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>

#define THREAD_STACK_SIZE PTHREAD_STACK_MIN
#define STACKSIZE SIGSTKSZ

void sa_segv_action( int sig, siginfo_t *info, void *arg )
{
   printf("Stack Overflow : Handler called\n");
   printf( "-- die --\n" );
   pthread_exit( NULL );
}


void* Hello(void *ptr)
{
   struct sigaltstack sa;
   char altstack[SIGSTKSZ];

   /* setup your alternate sig-stack */
   sa.ss_sp = altstack;
   sa.ss_size = STACKSIZE;
   sa.ss_flags = SS_ONSTACK;
   sigaltstack( &sa, NULL );


   fprintf(stderr,"%s"," Hello World!\n");
   return ptr;
}

int main()
{
   int error;
   pthread_t id;
   pthread_attr_t  attr;
   char *ptr;
   size_t size;
   int stack_size;

   struct sigaction act;

   /* setup a sighandler and specify we want
    * it delivered on the alternate stack
    */
   act.sa_sigaction = sa_segv_action;
   act.sa_flags = SA_SIGINFO | SA_ONSTACK;
   sigaction( SIGSEGV, &act, 0);

   ptr = (char *)calloc(5,sizeof(char));

   error = pthread_attr_init(&attr);
   pthread_attr_getstacksize(&attr,&size);
   printf("Initial  stack size is : %d\n",size);

   stack_size = THREAD_STACK_SIZE;
   if (stack_size < PTHREAD_STACK_MIN) {
       stack_size = PTHREAD_STACK_MIN;
   }
   if ((error=pthread_attr_setstacksize(&attr, stack_size)) != 0)
   {
       printf("\n error number is : %d \n",error);
       return -1;
   }
   pthread_attr_getstacksize(&attr,&size);
   printf("After resizing the stack size is : %d\n",size);
   error = pthread_create(&id,&attr,Hello,ptr);
   printf("Going for sleep after creating the thread\n");
   sleep(5);
   return 0;

}



Powered by YaBB 1 Gold - SP 1.4!
Forum software copyright © 2000-2004 Yet another Bulletin Board