Linux Newbie help
 help / color / mirror / Atom feed
* why does this program crash while using setcontext?
@ 2003-01-20  6:10 Lee Chin
  2003-01-20 14:32 ` Steven Smith
  0 siblings, 1 reply; 5+ messages in thread
From: Lee Chin @ 2003-01-20  6:10 UTC (permalink / raw)
  To: linux-newbie

#include <ucontext.h>
#include <stdio.h>

ucontext_t mainucp;
ucontext_t fooucp;
int flag = 0;

int foo()
{
    printf("(2) foo setting context\n");
    getcontext(&fooucp);
    if (!flag)
    {
        flag = 1;
        setcontext(&mainucp);
    }
    printf("(3) foo done\n");
    return 0;
}

void eleven()
{
    printf("(1) calling foo\n");
    foo();
    printf("(4) foo now finished\n");
}

void ten()
{
    eleven();
}

void nine()
{
    ten();
}

void eight()
{
    nine();
}

void seven()
{
    eight();
}

void six()
{
    seven();
}

void five()
{
    six();
}

void four()
{
    five();
}

void three()
{
    four();
}

void two()
{
    three();
}

void one()
{
    two();
}

int main()
{
    getcontext(&mainucp);
    if (!flag)
    {
        one();
    }
    else
    {
        printf("(2.5) main again\n");
        setcontext(&fooucp);
    }
}

~                                               
-- 
__________________________________________________________
Sign-up for your own FREE Personalized E-mail at Mail.com
http://www.mail.com/?sr=signup

Meet Singles
http://corp.mail.com/lavalife

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: why does this program crash while using setcontext?
  2003-01-20  6:10 Lee Chin
@ 2003-01-20 14:32 ` Steven Smith
  0 siblings, 0 replies; 5+ messages in thread
From: Steven Smith @ 2003-01-20 14:32 UTC (permalink / raw)
  To: Lee Chin; +Cc: linux-newbie

[-- Attachment #1: Type: text/plain, Size: 3920 bytes --]

I think this problem is largely my fault; I should have been more
clear last time I posted.  Feel free to insult me.

I think the program below is trying to:

1) have main() record its context immediately.  Call this the
	main context.
2) Call foo() indirectly through one().
3) Record foo()'s context.  Call this the foo context.
4) Switch back to the main context.
5) Switch back to the foo context.
6) Return back from foo() to main() and then exit.

Now, the problem is that the various contexts are all running on the
same stack.  This means that the bit of main() which runs between
steps 4 and 5 is mangling the foo context, and so step 6 doesn't work.

The way to avoid this is to have the two contexts operating on
different stacks.  The main context can happily run on the process
stack, but one will need to be allocated for the foo context.
An array of chars is perfectly good for this; the usual size
is SIGSTKSZ, defined in signal.h.  In addition, we need to tell
the ucontext functions to use this stack.  Unfortunately, there's
no (easy) way to copy the current stack onto the context stack,
and so we need to use makecontext() rather than getcontext().

This means the design of the program looks more like this:

1) Have main() record its context.  Call this the main context.
2) Have main() construct a context which will invoke foo() on a
	different stack.  Call this the foo context.
3) Have main() invoke the foo context.
4) Switch back to the main context.
5) Switch back to the foo context.
6) Let the foo context return.  This will cause the context library
	to automatically switch back to the main context, which
	can then return and exit the program.

I've shown these changes below.

> ucontext_t mainucp;
> ucontext_t fooucp;
> int flag = 0;
char stack[SIGSTKSZ];

> int foo()
> {
>     printf("(2) foo setting context\n");

>     getcontext(&fooucp);
Kill this line - the foo context has already been constructed.

>     if (!flag)
>     {
>         flag = 1;

>         setcontext(&mainucp);
Replace this line with:
	  swapcontext(&fooucp, &mainucp);
We need swapcontext() rather than setcontext() so as the foo
context resumes from here, rather than the entry to one(),
which would cause an infinite loop.

>     }
>     printf("(3) foo done\n");
>     return 0;
> }

<snip deeply nested call to foo() from one()>

> int main()
> {
Insert
	getcontext(&fooucp);
	fooucp.uc_link = &mainucp;
	fooucp.uc_stack.ss_sp = stack;
	fooucp.uc_stack.ss_size = sizeof(stack);
	makecontext(&fooucp, one, 0);
The uc_link line says to return the main context if the foo context
ever returns.  The uc_stack lines are just setting up the stack,
and the makecontext() modified the foo context so that it calls
one() with 0 arguments.

For various reasons, primarily historical, contexts which are passed
to makecontext() must first be initialised with getcontext(), even
though makecontext() overwrites or makes redundant 95% of the work
which getcontext() did.

>     getcontext(&mainucp);
>     if (!flag)
>     {

>         one();
Replace this line with
	setcontext(&fooucp);
Note that this is setcontext() and not swapcontext(); if we used
swapcontext(), then the main context would resume from here
rather than the call to getcontext(), above, and so the else
branch of the if would never run.

>     }
>     else
>     {
>         printf("(2.5) main again\n");

>         setcontext(&fooucp);
Replace this line with
	swapcontext(&mainucp, &fooucp);
We need swapcontext() here, rather than setcontext(), because we
want the main context to resume here rather than at the getcontext(),
to avoid an infinite loop.

>     }
Insert:
	return 0;
:)
> }

Hopefully, that's a little clearer.

In general, it's a good idea to use swapcontext() rather than
setcontext() if at all possible, because then functions return to the
same place as they were called from, which is a lot easier to think
about.

Steven.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: why does this program crash while using setcontext?
@ 2003-01-20 16:12 Lee Chin
  0 siblings, 0 replies; 5+ messages in thread
From: Lee Chin @ 2003-01-20 16:12 UTC (permalink / raw)
  To: sos22; +Cc: linux-newbie

Thanks Steven... this works great... I now understand this api well thanks to you!

Best Wishes,
Lee
----- Original Message -----
From: Steven Smith <sos22@cam.ac.uk> 
Date: Mon, 20 Jan 2003 14:32:40 +0000
To: Lee Chin <leechin@mail.com>
Subject: Re: why does this program crash while using setcontext?

> I think this problem is largely my fault; I should have been more
> clear last time I posted.  Feel free to insult me.
> 
> I think the program below is trying to:
> 
> 1) have main() record its context immediately.  Call this the
> 	main context.
> 2) Call foo() indirectly through one().
> 3) Record foo()'s context.  Call this the foo context.
> 4) Switch back to the main context.
> 5) Switch back to the foo context.
> 6) Return back from foo() to main() and then exit.
> 
> Now, the problem is that the various contexts are all running on the
> same stack.  This means that the bit of main() which runs between
> steps 4 and 5 is mangling the foo context, and so step 6 doesn't work.
> 
> The way to avoid this is to have the two contexts operating on
> different stacks.  The main context can happily run on the process
> stack, but one will need to be allocated for the foo context.
> An array of chars is perfectly good for this; the usual size
> is SIGSTKSZ, defined in signal.h.  In addition, we need to tell
> the ucontext functions to use this stack.  Unfortunately, there's
> no (easy) way to copy the current stack onto the context stack,
> and so we need to use makecontext() rather than getcontext().
> 
> This means the design of the program looks more like this:
> 
> 1) Have main() record its context.  Call this the main context.
> 2) Have main() construct a context which will invoke foo() on a
> 	different stack.  Call this the foo context.
> 3) Have main() invoke the foo context.
> 4) Switch back to the main context.
> 5) Switch back to the foo context.
> 6) Let the foo context return.  This will cause the context library
> 	to automatically switch back to the main context, which
> 	can then return and exit the program.
> 
> I've shown these changes below.
> 
> > ucontext_t mainucp;
> > ucontext_t fooucp;
> > int flag = 0;
> char stack[SIGSTKSZ];
> 
> > int foo()
> > {
> >     printf("(2) foo setting context\n");
> 
> >     getcontext(&fooucp);
> Kill this line - the foo context has already been constructed.
> 
> >     if (!flag)
> >     {
> >         flag = 1;
> 
> >         setcontext(&mainucp);
> Replace this line with:
> 	  swapcontext(&fooucp, &mainucp);
> We need swapcontext() rather than setcontext() so as the foo
> context resumes from here, rather than the entry to one(),
> which would cause an infinite loop.
> 
> >     }
> >     printf("(3) foo done\n");
> >     return 0;
> > }
> 
> <snip deeply nested call to foo() from one()>
> 
> > int main()
> > {
> Insert
> 	getcontext(&fooucp);
> 	fooucp.uc_link = &mainucp;
> 	fooucp.uc_stack.ss_sp = stack;
> 	fooucp.uc_stack.ss_size = sizeof(stack);
> 	makecontext(&fooucp, one, 0);
> The uc_link line says to return the main context if the foo context
> ever returns.  The uc_stack lines are just setting up the stack,
> and the makecontext() modified the foo context so that it calls
> one() with 0 arguments.
> 
> For various reasons, primarily historical, contexts which are passed
> to makecontext() must first be initialised with getcontext(), even
> though makecontext() overwrites or makes redundant 95% of the work
> which getcontext() did.
> 
> >     getcontext(&mainucp);
> >     if (!flag)
> >     {
> 
> >         one();
> Replace this line with
> 	setcontext(&fooucp);
> Note that this is setcontext() and not swapcontext(); if we used
> swapcontext(), then the main context would resume from here
> rather than the call to getcontext(), above, and so the else
> branch of the if would never run.
> 
> >     }
> >     else
> >     {
> >         printf("(2.5) main again\n");
> 
> >         setcontext(&fooucp);
> Replace this line with
> 	swapcontext(&mainucp, &fooucp);
> We need swapcontext() here, rather than setcontext(), because we
> want the main context to resume here rather than at the getcontext(),
> to avoid an infinite loop.
> 
> >     }
> Insert:
> 	return 0;
> :)
> > }
> 
> Hopefully, that's a little clearer.
> 
> In general, it's a good idea to use swapcontext() rather than
> setcontext() if at all possible, because then functions return to the
> same place as they were called from, which is a lot easier to think
> about.
> 
> Steven.

-- 
__________________________________________________________
Sign-up for your own FREE Personalized E-mail at Mail.com
http://www.mail.com/?sr=signup

Meet Singles
http://corp.mail.com/lavalife

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: why does this program crash while using setcontext?
@ 2003-01-21  8:13 Lee Chin
  2003-01-21 16:39 ` Steven Smith
  0 siblings, 1 reply; 5+ messages in thread
From: Lee Chin @ 2003-01-21  8:13 UTC (permalink / raw)
  To: sos22, leechin; +Cc: linux-newbie

Steven
One thing I dont understand is why if I use setcontext instead of swapcontext in the following program, I crash?  Look at where I commented out my swapcontext

Thanks
Lee
#include <ucontext.h>
#include <stdio.h>
#include <setjmp.h>

ucontext_t mainucp;
ucontext_t fooucp;

char stack[SIGSTKSZ];
int flag = 0;

int foo()
{
    printf("(2) foo setting context\n");
    if (!flag)
    {
        flag = 1;
        swapcontext(&fooucp, &mainucp);
    }
    printf("(3) foo done\n");
    return 0;
}

void eleven()
{
    printf("(1) calling foo\n");
    foo();
    printf("(4) foo now finished\n");
}

void ten()
{
    eleven();
}

void nine()
{
    ten();
}

void eight()
{
    nine();
}

void seven()
{
    eight();
}

void six()
{
    seven();
}

void five()
{
    six();
}

void four()
{
    five();
}

void three()
{
    four();
}

void two()
{
    three();
}

void one()
{
    two();
}

int main()
{
    getcontext(&fooucp);
    fooucp.uc_link = &mainucp;
    fooucp.uc_stack.ss_sp = stack;
    fooucp.uc_stack.ss_size = sizeof(stack);
    makecontext(&fooucp, one, 0);
    getcontext(&mainucp);
    printf("(1, 2.2) main checking flag flag\n");
    if (!flag)
    {
        setcontext(&fooucp);
    }
    else
    {
        printf("(2.5) main again\n");
        // HERE IS WHERE I COMMENTED OUT 
        // swapcontext(&mainucp, &fooucp);
        setcontext(&fooucp);
    }
}
~                                                                                    
~                                                                                    
----- Original Message -----
From: Steven Smith <sos22@cam.ac.uk> 
Date: Mon, 20 Jan 2003 14:32:40 +0000
To: Lee Chin <leechin@mail.com>
Subject: Re: why does this program crash while using setcontext?

> I think this problem is largely my fault; I should have been more
> clear last time I posted.  Feel free to insult me.
> 
> I think the program below is trying to:
> 
> 1) have main() record its context immediately.  Call this the
> 	main context.
> 2) Call foo() indirectly through one().
> 3) Record foo()'s context.  Call this the foo context.
> 4) Switch back to the main context.
> 5) Switch back to the foo context.
> 6) Return back from foo() to main() and then exit.
> 
> Now, the problem is that the various contexts are all running on the
> same stack.  This means that the bit of main() which runs between
> steps 4 and 5 is mangling the foo context, and so step 6 doesn't work.
> 
> The way to avoid this is to have the two contexts operating on
> different stacks.  The main context can happily run on the process
> stack, but one will need to be allocated for the foo context.
> An array of chars is perfectly good for this; the usual size
> is SIGSTKSZ, defined in signal.h.  In addition, we need to tell
> the ucontext functions to use this stack.  Unfortunately, there's
> no (easy) way to copy the current stack onto the context stack,
> and so we need to use makecontext() rather than getcontext().
> 
> This means the design of the program looks more like this:
> 
> 1) Have main() record its context.  Call this the main context.
> 2) Have main() construct a context which will invoke foo() on a
> 	different stack.  Call this the foo context.
> 3) Have main() invoke the foo context.
> 4) Switch back to the main context.
> 5) Switch back to the foo context.
> 6) Let the foo context return.  This will cause the context library
> 	to automatically switch back to the main context, which
> 	can then return and exit the program.
> 
> I've shown these changes below.
> 
> > ucontext_t mainucp;
> > ucontext_t fooucp;
> > int flag = 0;
> char stack[SIGSTKSZ];
> 
> > int foo()
> > {
> >     printf("(2) foo setting context\n");
> 
> >     getcontext(&fooucp);
> Kill this line - the foo context has already been constructed.
> 
> >     if (!flag)
> >     {
> >         flag = 1;
> 
> >         setcontext(&mainucp);
> Replace this line with:
> 	  swapcontext(&fooucp, &mainucp);
> We need swapcontext() rather than setcontext() so as the foo
> context resumes from here, rather than the entry to one(),
> which would cause an infinite loop.
> 
> >     }
> >     printf("(3) foo done\n");
> >     return 0;
> > }
> 
> <snip deeply nested call to foo() from one()>
> 
> > int main()
> > {
> Insert
> 	getcontext(&fooucp);
> 	fooucp.uc_link = &mainucp;
> 	fooucp.uc_stack.ss_sp = stack;
> 	fooucp.uc_stack.ss_size = sizeof(stack);
> 	makecontext(&fooucp, one, 0);
> The uc_link line says to return the main context if the foo context
> ever returns.  The uc_stack lines are just setting up the stack,
> and the makecontext() modified the foo context so that it calls
> one() with 0 arguments.
> 
> For various reasons, primarily historical, contexts which are passed
> to makecontext() must first be initialised with getcontext(), even
> though makecontext() overwrites or makes redundant 95% of the work
> which getcontext() did.
> 
> >     getcontext(&mainucp);
> >     if (!flag)
> >     {
> 
> >         one();
> Replace this line with
> 	setcontext(&fooucp);
> Note that this is setcontext() and not swapcontext(); if we used
> swapcontext(), then the main context would resume from here
> rather than the call to getcontext(), above, and so the else
> branch of the if would never run.
> 
> >     }
> >     else
> >     {
> >         printf("(2.5) main again\n");
> 
> >         setcontext(&fooucp);
> Replace this line with
> 	swapcontext(&mainucp, &fooucp);
> We need swapcontext() here, rather than setcontext(), because we
> want the main context to resume here rather than at the getcontext(),
> to avoid an infinite loop.
> 
> >     }
> Insert:
> 	return 0;
> :)
> > }
> 
> Hopefully, that's a little clearer.
> 
> In general, it's a good idea to use swapcontext() rather than
> setcontext() if at all possible, because then functions return to the
> same place as they were called from, which is a lot easier to think
> about.
> 
> Steven.

-- 
__________________________________________________________
Sign-up for your own FREE Personalized E-mail at Mail.com
http://www.mail.com/?sr=signup

Meet Singles
http://corp.mail.com/lavalife

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: why does this program crash while using setcontext?
  2003-01-21  8:13 why does this program crash while using setcontext? Lee Chin
@ 2003-01-21 16:39 ` Steven Smith
  0 siblings, 0 replies; 5+ messages in thread
From: Steven Smith @ 2003-01-21 16:39 UTC (permalink / raw)
  To: Lee Chin; +Cc: linux-newbie

[-- Attachment #1: Type: text/plain, Size: 2417 bytes --]

One day, I'll learn to think before posting, and possibly check
that whatever I'm suggesting actually works...

> One thing I dont understand is why if I use setcontext instead of
> swapcontext in the following program, I crash?  Look at where I
> commented out my swapcontext
The problem here is that the foo context is being invoked twice
with the same set of registers, but a different stack setup.

The first time foo is invoked, it runs through one(), setting up a
return stack in the stack buffer, before invoking the main context.
The main context then re-invokes the foo context, which returns back
through its call stack, destroying it in the process.  main then
invokes foo again, resulting in weird stack corruption problems
and a crash.  One possible fix is shown below.

> #include <ucontext.h>
> #include <stdio.h>
> #include <setjmp.h>
> 
> ucontext_t mainucp;
> ucontext_t fooucp;
> 
> char stack[SIGSTKSZ];
Add another stack buffer:
char ostack[SIGSTKSZ];

<snip unchanged code>
> int main()
> {
Add
	volatile int count;
	count = 0;
This counts the number of times the main context has resumed.

>     getcontext(&fooucp);
>     fooucp.uc_link = &mainucp;
Note that when the foo context returns, the main context is invoked
immediately i.e. without trying to save foo's registers
(which wouldn't actually make much sense).  This means that
the foo context now contains registers suitable for running
foo(), but a stack suitable for running the end of one().  This
is a bad thing.

>     fooucp.uc_stack.ss_sp = stack;
>     fooucp.uc_stack.ss_size = sizeof(stack);
>     makecontext(&fooucp, one, 0);
>     getcontext(&mainucp);
Add
	if (count == 1) {
		memcpy(ostack, stack, sizeof(stack));
	} else if (count > 1) {
		memcpy(stack, ostack, sizeof(stack));
	}
	count++;
This saves a copy of the foo context's stack the first time it switches
to main, and then restores it on later occasions.  This is ugly,
but it's probably the only way you're going to be able to re-use
contexts which have returned.

>     printf("(1, 2.2) main checking flag flag\n");
>     if (!flag)
>     {
>         setcontext(&fooucp);
>     }
>     else
>     {
>         printf("(2.5) main again\n");
>         setcontext(&fooucp);
>     }
> }

I should probably apologise for not going into nearly enough detail
for such an obscure API.

Steven.

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2003-01-21 16:39 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-01-21  8:13 why does this program crash while using setcontext? Lee Chin
2003-01-21 16:39 ` Steven Smith
  -- strict thread matches above, loose matches on Subject: below --
2003-01-20 16:12 Lee Chin
2003-01-20  6:10 Lee Chin
2003-01-20 14:32 ` Steven Smith

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox