possible race condition with fork and GLUT idle callback? weird problem
Web Server forum
Back To The Forum Home!Search!Private Messaging System

Web Server Talk Web Server Talk > Unix and Linux reviews > Free Unix support > Unix Programming > possible race condition with fork and GLUT idle callback? weird problem




  Last Thread   Next Thread Next
  Show Printable Version Email this Page Subscribe to this Thread      Post New Thread    Post A Reply      

    possible race condition with fork and GLUT idle callback? weird problem  
atv


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
11-16-06 06:17 PM

Ok,
I'm busy building an opengl application with glut. This doesn't really
matter, but just so you can put it in the right context. I have a
callback called idle(), which is called alot of times.

Now, i have one piece of code in here, which when i compile and run it
(i use xcode) i see this strange thing in the run log. It seems almost
like a race condition. I duplicated this by making a small c program
and calling a forkthis() function with the code in question in it in a
tight for loop. But this reproduction doesn't display anything weird. I
wonder if GLUT calls the idle() function faster then a for(;;) loop
could.

Anyway, here is what i see in the run log once running. The first fork
runs fine, after that it goes haywire:

[Session started at 2006-11-16 18:31:12 +0100.]
No log handling enabled - turning on stderr logging
snmpget: Timeout (No route to host)
Forking new processSNMPv2-MIB::sysDescr.0
--lots of output--

Now here is when it goes increasinly wrong (or so it seems):
snmpget: Timeout (No route to host)
No log handling enabled - turning on stderr logging
snmpget: Failure in sendto (Host is down)
Forking new processChild returnedForking new
processSNMPv2-MIB::sysDescr.0 = STRING: Dar

And this seems to grow exponentially
 (forkingnewprocess;childreturned;forking
newprocessetc) until the entire
screen is filled.

So, like i said, i tried and reproduce it by making this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

int forkthis(void);
pid_t val=1;

int main(void)
{
for(;;) {
forkthis();
}
}

int forkthis(void)
{
int status;

if(wait4(val,&status,WNOHANG,NULL)==val)
printf("Child returned with pid %d\n",val);

if(kill(val,0)) {
printf("Forking new process\n");

if((val=fork())==-1) {
fprintf(stderr,"Could not fork\n");
exit(1);}

else if(!val) {
printf("I am the child with pid: %d\n",getpid());
exit(1);
}
else {
printf("I am the parent. My pid is %d and my child pid is
%d\n",getpid(),val);
}
}
}

But this outputs correctly:
Forking new process
I am the child with pid: 6029
I am the parent. My pid is 5845 and my child pid is 6029
Child returned with pid 6029
Forking new process
I am the child with pid: 6030
I am the parent. My pid is 5845 and my child pid is 6030
Child returned with pid 6030
Forking new process

etc. The code posted is exactly the same as in the application itself,
only without the for(;;) call in main. I have thought about the
possibility that

1. the loop is run once ok
2. idle() is called again while child has not yet returned or is in the
process of doing so (this would explain why i get so much "Forking new
process" and right after the "Child returned". While it is checking to
see if the process actually exists with the kill() function, it did
just return and forks a new process. This would introduce a race
condition i'd rather not have :-)

Is this theory is sound, how do i fix it ? :-P
Thanks for any replies!
gr,






[ Post a follow-up to this message ]



    Re: possible race condition with fork and GLUT idle callback? weird problem  
Jens Thoms Toerring


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
11-19-06 06:16 PM

atv <alef@xs4all.nl> wrote:
> I'm busy building an opengl application with glut. This doesn't really
> matter, but just so you can put it in the right context. I have a
> callback called idle(), which is called alot of times.

> Now, i have one piece of code in here, which when i compile and run it
> (i use xcode) i see this strange thing in the run log. It seems almost
> like a race condition. I duplicated this by making a small c program
> and calling a forkthis() function with the code in question in it in a
> tight for loop. But this reproduction doesn't display anything weird. I
> wonder if GLUT calls the idle() function faster then a for(;;) loop
> could.

> Anyway, here is what i see in the run log once running. The first fork
> runs fine, after that it goes haywire:

> [Session started at 2006-11-16 18:31:12 +0100.]
> No log handling enabled - turning on stderr logging
> snmpget: Timeout (No route to host)
> Forking new processSNMPv2-MIB::sysDescr.0
> --lots of output--

> Now here is when it goes increasinly wrong (or so it seems):
> snmpget: Timeout (No route to host)
> No log handling enabled - turning on stderr logging
> snmpget: Failure in sendto (Host is down)
> Forking new processChild returnedForking new
> processSNMPv2-MIB::sysDescr.0 = STRING: Dar

> And this seems to grow exponentially
>  (forkingnewprocess;childreturned;forking
newprocessetc) until the entire
> screen is filled.

If there's something "exponentially" going on my first guess would be
that the child doesn't terminate once it has done its job but instead
runs also the parents code and creates new children of its own...

> So, like i said, i tried and reproduce it by making this:

It's always problematic not to post code that exhibits the problem
but instead code that does not - how are we supposed to see what's
going wrong when all we have is code that works as expected?

> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <sys/types.h>

> int forkthis(void);
> pid_t val=1;

> int main(void)
> {
>         for(;;) {
>         forkthis();
>         }
> }

> int forkthis(void)
> {
>         int status;

>         if(wait4(val,&status,WNOHANG,NULL)==val)

Why don't you just use waitpid()?

>         printf("Child returned with pid %d\n",val);

>         if(kill(val,0)) {
>         printf("Forking new process\n");

>         if((val=fork())==-1) {
>         fprintf(stderr,"Could not fork\n");
>         exit(1);}

>         else if(!val) {
>         printf("I am the child with pid: %d\n",getpid());
>         exit(1);
>         }
>         else {
>         printf("I am the parent. My pid is %d and my child pid is
> %d\n",getpid(),val);
>         }
>         }
> }

> But this outputs correctly:
> Forking new process
> I am the child with pid: 6029
> I am the parent. My pid is 5845 and my child pid is 6029
> Child returned with pid 6029
> Forking new process
> I am the child with pid: 6030
> I am the parent. My pid is 5845 and my child pid is 6030
> Child returned with pid 6030
> Forking new process

That's one possible output - but the output of the parent after the
fork() also could come before the one from the child, there's no
guarantee that the child will run first (on a SMP machine they could
even run in parallel).

> etc. The code posted is exactly the same as in the application itself,
> only without the for(;;) call in main.

Since it behaves differently please allow me to have some doubts
about the code for your "real" program being exactly the same...

> I have thought about the  possibility that

> 1. the loop is run once ok
> 2. idle() is called again while child has not yet returned or is in the
> process of doing so (this would explain why i get so much "Forking new
> process" and right after the "Child returned". While it is checking to
> see if the process actually exists with the kill() function, it did
> just return and forks a new process. This would introduce a race
> condition i'd rather not have :-)

Please could you rewrite that sentence in English that makes sense?
I have tried to parse it several times but don't understand it.

There is definitely a chance that between the call of wait4() and
the call of kill() the child dies, so wait4() returns 0 and kill()
return -1. But I don't see why you have to call both wait4() and
kill(). In that case you wouldn't be reaping in the return value of
the child (leaving a zombie behind) and "Child returned with pid"
wouldn't be printed out for that child.

But, as far as I can see, there's no need at all for the call of
kill(), you could simply do e.g.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int fork_this(void);

pid_t val = -1;

int main( void )
{
for ( ; ; )
fork_this( );

return 0;
}

int fork_this( void )
{
int status;

if ( waitpid( val, &status, WNOHANG ) == val )
{
if ( val != -1 )
printf( "Child returned with pid %d\n", val );

printf( "Forking new process\n" );

if ( ( val = fork( ) ) == -1 )
{
fprintf( stderr, "Could not fork\n" );
exit( 1 );
}
else if ( val == 0 )
{
printf("I am the child with pid: %d\n", getpid( ) );
sleep( 2 );
exit( 1 );
}
else
printf( "I am the parent. My pid is %d and my child pid is %d\n",
getpid( ), val );
}
else if ( val != 1 )
{
printf( "Child isn't dead yet\n" );
sleep( 1 );
}

return 0;
}

Please note: setting up val to -1 at the start guarantees that waitpid()
will return -1 (which then is equal to val) so the very first child gets
spawned.
Regards, Jens
--
\   Jens Thoms Toerring  ___     jt@toerring.de
\__________________________     http://toerring.de





[ Post a follow-up to this message ]



    Sponsored Links  




 





   All times are GMT. The time now is 06:52 PM.      Post New Thread    Post A Reply      
  Last Thread   Next Thread Next


Most Popular forums 

Forum Jump:
Rate This Thread:

Forum Rules:
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is OFF
vB code is ON
Smilies are ON
[IMG] code is OFF
 
Medical and Health forum | Computer Games Reviews | Graphics design forum

Back To The Top
Home | Usercp | Faq | Register