linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* K 2.6 test6 strange signal behaviour
@ 2003-10-20 13:01 Ken Foskey
  2003-10-20 13:48 ` Richard B. Johnson
  2003-10-20 20:28 ` Andrew Morton
  0 siblings, 2 replies; 7+ messages in thread
From: Ken Foskey @ 2003-10-20 13:01 UTC (permalink / raw)
  To: linux-kernel

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


I have a problem with signals.

I get multiple signals from a single execution of the program.  I have
attached a stripped source.  Here is the critical snippet, you can see
the signal handler being set before each call:

	signal( SIGSEGV,	SignalHdl );
	signal( SIGBUS,		SignalHdl );
	fprintf( stderr, "Running \n" );
	result = func( eT, p );
	fprintf( stderr, "Finished \n" );
	signal( SIGSEGV,	SIG_DFL );
	signal( SIGBUS,		SIG_DFL );

When I run the code, that does 2 derefs of NULL you will see 2 instances
of "Running" and the handler is not invoked at all for the second time.

./solar:


Getting from NULL
Setting Jump
Running
Signal 11 caught
After jump
Setting to NULL
Setting Jump
Running
Segmentation fault

I am running debian version of K 2.6 test6.  This has occurred on all
versions of K2.6 though, not specific.

-- 
Thanks
KenF
OpenOffice.org developer

[-- Attachment #2: solar.c --]
[-- Type: text/x-c, Size: 2448 bytes --]

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

/*************************************************************************
|*	Typdeclarations for memory access test functions
*************************************************************************/
typedef int (*TestFunc)( void* );

/*************************************************************************
*************************************************************************/
static jmp_buf check_env;
static int bSignal;
static void SignalHdl( int sig )
{
  bSignal = 1;
  
  fprintf( stderr, "Signal %d caught\n", sig );
  longjmp( check_env, sig );
}

/*************************************************************************
*************************************************************************/
void check( TestFunc func, void* p )
{
  int result;

  fprintf( stderr, "Setting Jump\n" );
  if ( !setjmp( check_env ) )
  {
	signal( SIGSEGV,	SignalHdl );
	signal( SIGBUS,		SignalHdl );
    fprintf( stderr, "Running \n" );
	result = func( p );
    fprintf( stderr, "Finished \n" );
	signal( SIGSEGV,	SIG_DFL );
	signal( SIGBUS,		SIG_DFL );
  }
  fprintf( stderr, "After jump \n" );
}

/*************************************************************************
*************************************************************************/
static int GetAtAddress( void* p )
{
  return *((char*)p);
}

/*************************************************************************
*************************************************************************/
static int SetAtAddress( void* p )
{
  return *((char*)p)	= 0;
}

/*************************************************************************
*************************************************************************/
void CheckGetAccess( void* p )
{
  check( (TestFunc)GetAtAddress, p );
}
/*************************************************************************
*************************************************************************/
void CheckSetAccess( void* p )
{
  check( (TestFunc)SetAtAddress, p );
}

/*************************************************************************
*************************************************************************/
int main( int argc, char* argv[] )
{
  {
	char* p = NULL;
	fprintf( stderr, "Getting from NULL\n" );
    CheckGetAccess( p );
	fprintf( stderr, "Setting to NULL\n" );
    CheckSetAccess( p );
	fprintf( stderr, "After Setting to NULL\n" );
  }

  exit( 0 );
}

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

* Re: K 2.6 test6 strange signal behaviour
  2003-10-20 13:01 K 2.6 test6 strange signal behaviour Ken Foskey
@ 2003-10-20 13:48 ` Richard B. Johnson
  2003-10-20 19:26   ` Ken Foskey
  2003-10-20 20:28 ` Andrew Morton
  1 sibling, 1 reply; 7+ messages in thread
From: Richard B. Johnson @ 2003-10-20 13:48 UTC (permalink / raw)
  To: Ken Foskey; +Cc: Linux kernel

On Mon, 20 Oct 2003, Ken Foskey wrote:

>
> I have a problem with signals.
>
> I get multiple signals from a single execution of the program.  I have
> attached a stripped source.  Here is the critical snippet, you can see
> the signal handler being set before each call:
>
> 	signal( SIGSEGV,	SignalHdl );
> 	signal( SIGBUS,		SignalHdl );
> 	fprintf( stderr, "Running \n" );
> 	result = func( eT, p );
> 	fprintf( stderr, "Finished \n" );
> 	signal( SIGSEGV,	SIG_DFL );
> 	signal( SIGBUS,		SIG_DFL );
>
> When I run the code, that does 2 derefs of NULL you will see 2 instances
> of "Running" and the handler is not invoked at all for the second time.
>
> ./solar:

You really didn't give enough information, but I think your
signal() is not set up as BSD signals as you expect. I encountered
such a problem several years ago and reported it to the people
who wrote the 'C' runtime library. They were kind enough to respond
with the usual "you are an idiot..." response, but buried in the
response was the information that I needed. You can bypass all
those problems by using sigaction(). You can set the flags to
give the required response. I think you want SA_RESTART in the
flags to give you the response you expect.

Also, if you have a longjmp() in your handler code, you can
trash your local variables in the main-line code. You want
to try to perform whatever it is that you are doing without
setjmp()/longjmp() or sigsetjmp()/siglongjmp().

Cheers,
Dick Johnson
Penguin : Linux version 2.4.22 on an i686 machine (797.90 BogoMips).
            Note 96.31% of all statistics are fiction.



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

* Re: K 2.6 test6 strange signal behaviour
  2003-10-20 13:48 ` Richard B. Johnson
@ 2003-10-20 19:26   ` Ken Foskey
  2003-10-20 20:38     ` Richard B. Johnson
  0 siblings, 1 reply; 7+ messages in thread
From: Ken Foskey @ 2003-10-20 19:26 UTC (permalink / raw)
  To: root; +Cc: Linux kernel

On Mon, 2003-10-20 at 23:48, Richard B. Johnson wrote:
> On Mon, 20 Oct 2003, Ken Foskey wrote:
> 
> >
> > I have a problem with signals.
> >
> > I get multiple signals from a single execution of the program.  I have
> > attached a stripped source.  Here is the critical snippet, you can see
> > the signal handler being set before each call:
> >
> > 	signal( SIGSEGV,	SignalHdl );
> > 	signal( SIGBUS,		SignalHdl );
> > 	fprintf( stderr, "Running \n" );
> > 	result = func( eT, p );
> > 	fprintf( stderr, "Finished \n" );
> > 	signal( SIGSEGV,	SIG_DFL );
> > 	signal( SIGBUS,		SIG_DFL );
> >
> > When I run the code, that does 2 derefs of NULL you will see 2 instances
> > of "Running" and the handler is not invoked at all for the second time.
> >
> > ./solar:
> 
> You really didn't give enough information.

I provided sample code...

> , but I think your
> signal() is not set up as BSD signals as you expect. I encountered
> such a problem several years ago and reported it to the people
> who wrote the 'C' runtime library. They were kind enough to respond
> with the usual "you are an idiot..." response, but buried in the
> response was the information that I needed. You can bypass all
> those problems by using sigaction(). You can set the flags to
> give the required response. I think you want SA_RESTART in the
> flags to give you the response you expect.

The SA_RESTART option looks interesting.  Will tinker with this.  The
important thing that the K 2.6 developers must be aware if this code
works under K 2.4. This has changed between K 2.4 and K 2.6.  This has
lead to mysterious failures of existing programs, mine at least.

> Also, if you have a longjmp() in your handler code, you can
> trash your local variables in the main-line code. You want
> to try to perform whatever it is that you are doing without
> setjmp()/longjmp() or sigsetjmp()/siglongjmp().

The code works correctly on K 2.4. The signal function is called before
EVERY invocation just before the "Running" text and the output shows
that "Running" was output and yet signal( SIGSEGV, SignalHdl) does not
fire.

Here is the output again:

Getting from NULL
Setting Jump
Running
Signal 11 caught
After jump
Setting to NULL
Setting Jump
Running
Segmentation fault

I was looking for another error in the code, like longjmp trashing
variables however the code does not show problems (or crash) with that,
it simply does not honour the signal function.  The fact that there is
other "issues" with the code does not cover that fact however longjmp
may have some indirect bearing.

This is behaving differently from K 2.4.  either K 2.4 has a bug that
existing software does rely on like mine or K 2.6 has a bug.  If it is a
correction of a K 2.4 bug we need to ensure that people know about it.

-- 
Thanks
KenF
OpenOffice.org developer


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

* Re: K 2.6 test6 strange signal behaviour
  2003-10-20 13:01 K 2.6 test6 strange signal behaviour Ken Foskey
  2003-10-20 13:48 ` Richard B. Johnson
@ 2003-10-20 20:28 ` Andrew Morton
  2003-10-21  1:56   ` Ken Foskey
  1 sibling, 1 reply; 7+ messages in thread
From: Andrew Morton @ 2003-10-20 20:28 UTC (permalink / raw)
  To: Ken Foskey; +Cc: linux-kernel

Ken Foskey <foskey@optushome.com.au> wrote:
>
> I have a problem with signals.

You should be using sigsetjmp(), not setjmp().


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

* Re: K 2.6 test6 strange signal behaviour
  2003-10-20 19:26   ` Ken Foskey
@ 2003-10-20 20:38     ` Richard B. Johnson
  0 siblings, 0 replies; 7+ messages in thread
From: Richard B. Johnson @ 2003-10-20 20:38 UTC (permalink / raw)
  To: Ken Foskey; +Cc: Linux kernel

On Tue, 21 Oct 2003, Ken Foskey wrote:

> On Mon, 2003-10-20 at 23:48, Richard B. Johnson wrote:
> > On Mon, 20 Oct 2003, Ken Foskey wrote:
> >
> > >
> > > I have a problem with signals.
> > >
> > > I get multiple signals from a single execution of the program.  I have
> > > attached a stripped source.  Here is the critical snippet, you can see
> > > the signal handler being set before each call:
> > >
> > > 	signal( SIGSEGV,	SignalHdl );
> > > 	signal( SIGBUS,		SignalHdl );
> > > 	fprintf( stderr, "Running \n" );
> > > 	result = func( eT, p );
> > > 	fprintf( stderr, "Finished \n" );
> > > 	signal( SIGSEGV,	SIG_DFL );
> > > 	signal( SIGBUS,		SIG_DFL );
> > >
> > > When I run the code, that does 2 derefs of NULL you will see 2 instances
> > > of "Running" and the handler is not invoked at all for the second time.
> > >
> > > ./solar:
> >
> > You really didn't give enough information.
>
> I provided sample code...
>

There was no attached code when I received your email.
If the stuff above is 'sample code', then I don't know what
kind of compiler you are using because, at the very least, there
should be some curley-braces and an entry point. So, I made
some sample code. Could you please try it and tell us what
it does that is unexpected?


#include <stdio.h>
#include <unistd.h>
#include <setjmp.h>
#include <signal.h>

int function(int input, const char *cp) {
    return fprintf(stderr, cp, input);
}
jmp_buf env;
int (*funct)(int, const char *) = NULL;
void SignalHdl(int sig) {
    fprintf(stderr, "Signal received %d\n", sig);
    longjmp(env, sig);
}
int main() {
    int result;
    int times = 5;
    (void)signal(SIGSEGV, SignalHdl);
    (void)signal(SIGBUS,  SignalHdl);
    if(!setjmp(env)) {
        fprintf(stderr, "Started\n");
        result = funct(times, "Handler writes %d\n");
    }
    if(times--) {
        funct = function;
        fprintf(stderr, "Okay(%d)\n", times);
        result = funct(times, "Handler writes %d\n");
        fprintf(stderr, "Okay(%d)\n", times);
        funct = NULL;
        result = funct(1, "Handler writes %d\n");  // Segfault
    }
    return 0;
}

It all seems to work here with Linux-2.4.22, even though the
counter "times" really should not be relied upon after the
longjmp.

Started
Signal received 11
Okay(4)
Handler writes 4
Okay(4)
Signal received 11
Okay(3)
Handler writes 3
Okay(3)
Signal received 11
Okay(2)
Handler writes 2
Okay(2)
Signal received 11
Okay(1)
Handler writes 1
Okay(1)
Signal received 11
Okay(0)
Handler writes 0
Okay(0)
Signal received 11


Cheers,
Dick Johnson
Penguin : Linux version 2.4.22 on an i686 machine (797.90 BogoMips).
            Note 96.31% of all statistics are fiction.



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

* Re: K 2.6 test6 strange signal behaviour
  2003-10-20 20:28 ` Andrew Morton
@ 2003-10-21  1:56   ` Ken Foskey
  2003-11-05  8:11     ` Alex Riesen
  0 siblings, 1 reply; 7+ messages in thread
From: Ken Foskey @ 2003-10-21  1:56 UTC (permalink / raw)
  To: linux-kernel

On Tue, 2003-10-21 at 06:28, Andrew Morton wrote:
> Ken Foskey <foskey@optushome.com.au> wrote:
> >
> > I have a problem with signals.
> 
> You should be using sigsetjmp(), not setjmp().

No difference.  Note that this is K 2.6 specific, it "works" in K 2.4.

I am reading on sigaction now, I will recode with SA_RESTART tonight.  
I think this is not the solution because I am explicitly setting the
signal handler before every call.  I think this simply leaves the signal
handler active ie old BSD style.

I also received this comment:

> Unblock the signal handler before you raise the signal again.

I think this means sigprocmask with UNBLOCK.  "Should" this be
required.  After reading and Andrews comments I added a reset and
siglongjmp here is my current handler:

static void SignalHdl( int sig )
{
  bSignal = 1;
  
  fprintf( stderr, "Signal %d caught\n", sig );
  signal( sig, SIG_DFL );  /* reset handler back */
  siglongjmp( check_env, sig );  /* return to code */
}

I do have a work around, I am pursuing this because the signal handler
is behaving differently in K 2.6 than K 2.4.  The error may be mine
however it may also be a bug with the kernel.

-- 
Thanks
KenF
OpenOffice.org developer

Current code:

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

/*************************************************************************
|*	Typdeclarations for memory access test functions
*************************************************************************/
typedef int (*TestFunc)( void* );

/*************************************************************************
*************************************************************************/
static sigjmp_buf check_env;
static int bSignal;
static void SignalHdl( int sig )
{
  bSignal = 1;
  
  fprintf( stderr, "Signal %d caught\n", sig );
  signal( sig, SIG_DFL );
  siglongjmp( check_env, sig );
}

/*************************************************************************
*************************************************************************/
void check( TestFunc func, void* p )
{
  int result;

  fprintf( stderr, "Setting Jump\n" );
  if ( !sigsetjmp( check_env, 0 ) )
  {
	signal( SIGSEGV,	SignalHdl );
	signal( SIGBUS,		SignalHdl );
    fprintf( stderr, "Running \n" );
	result = func( p );
    fprintf( stderr, "Finished \n" );
	signal( SIGSEGV,	SIG_DFL );
	signal( SIGBUS,		SIG_DFL );
  }
  fprintf( stderr, "After jump \n" );
}

/*************************************************************************
*************************************************************************/
static int GetAtAddress( void* p )
{
  return *((char*)p);
}

/*************************************************************************
*************************************************************************/
static int SetAtAddress( void* p )
{
  return *((char*)p)	= 0;
}

/*************************************************************************
*************************************************************************/
void CheckGetAccess( void* p )
{
  check( (TestFunc)GetAtAddress, p );
}
/*************************************************************************
*************************************************************************/
void CheckSetAccess( void* p )
{
  check( (TestFunc)SetAtAddress, p );
}

/*************************************************************************
*************************************************************************/
int main( int argc, char* argv[] )
{
  {
	char* p = NULL;
	fprintf( stderr, "Getting from NULL\n" );
    CheckGetAccess( p );
	fprintf( stderr, "Setting to NULL\n" );
    CheckSetAccess( p );
	fprintf( stderr, "After Setting to NULL\n" );
  }

  exit( 0 );
}



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

* Re: K 2.6 test6 strange signal behaviour
  2003-10-21  1:56   ` Ken Foskey
@ 2003-11-05  8:11     ` Alex Riesen
  0 siblings, 0 replies; 7+ messages in thread
From: Alex Riesen @ 2003-11-05  8:11 UTC (permalink / raw)
  To: Ken Foskey; +Cc: linux-kernel

Ken Foskey, Tue, Oct 21, 2003 03:56:10 +0200:
> On Tue, 2003-10-21 at 06:28, Andrew Morton wrote:
> > Ken Foskey <foskey@optushome.com.au> wrote:
> > >
> > > I have a problem with signals.
> > 
> > You should be using sigsetjmp(), not setjmp().
> 
> No difference.  Note that this is K 2.6 specific, it "works" in K 2.4.
> 
> I am reading on sigaction now, I will recode with SA_RESTART tonight.  

recode it with SA_NOMASK (and please, remove all that forest around the
code if you post it here).

Can someone explain here, how exactly setjmp/longjmp breaks expected
behaviour?

> I think this is not the solution because I am explicitly setting the
> signal handler before every call.  I think this simply leaves the signal
> handler active ie old BSD style.

no. See the glibc source, posix/signal.c


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

end of thread, other threads:[~2003-11-05  8:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-10-20 13:01 K 2.6 test6 strange signal behaviour Ken Foskey
2003-10-20 13:48 ` Richard B. Johnson
2003-10-20 19:26   ` Ken Foskey
2003-10-20 20:38     ` Richard B. Johnson
2003-10-20 20:28 ` Andrew Morton
2003-10-21  1:56   ` Ken Foskey
2003-11-05  8:11     ` Alex Riesen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).