Linux Newbie help
 help / color / mirror / Atom feed
From: Steven Smith <sos22@cam.ac.uk>
To: Lee Chin <leechin@mail.com>
Cc: linux-newbie@vger.kernel.org
Subject: Re: why does this program crash while using setcontext?
Date: Tue, 21 Jan 2003 16:39:34 +0000	[thread overview]
Message-ID: <20030121163934.GA4303@cam.ac.uk> (raw)
In-Reply-To: <20030121081327.69768.qmail@mail.com>

[-- 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 --]

  reply	other threads:[~2003-01-21 16:39 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-01-21  8:13 why does this program crash while using setcontext? Lee Chin
2003-01-21 16:39 ` Steven Smith [this message]
  -- 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030121163934.GA4303@cam.ac.uk \
    --to=sos22@cam.ac.uk \
    --cc=leechin@mail.com \
    --cc=linux-newbie@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox