[comp.lang.c++] Question about C++ signal handling

fkho@watdragon.waterloo.edu (Frederick K. Ho) (04/23/91)

Hi, I would like to know if anyone tried to register a signal inside a
member function with the callback signal handler being another member
function of the same class?

I have experiencing trouble inside the wakeup routine where I got BUS
error (alignment error). The this pointer seems to be corrupted.
Here's what I did:

class A
{
private:
	int	to;
public:
	A();
	~A();
	f();
	timeout();
};

A::timeout()
{
	to = 1;
}

A::f()
{
	// register the signal
	::signal(SIGALRM, timeout);

	 ...
}


Has I done anything wrong?

	//fred
	U. of Waterloo

-- 
Internet:  fkho@watdragon.waterloo.{edu|ca}
UUCP:	   {ihnp4,decvax,uunet,utai, ...}!watmath!watdragon!fkho
Bitnet:	   fkho@water.BITNET, fkho@water.uwaterloo.ca

steve@taumet.com (Stephen Clamage) (04/23/91)

fkho@watdragon.waterloo.edu (Frederick K. Ho) writes:

>Hi, I would like to know if anyone tried to register a signal inside a
>member function with the callback signal handler being another member
>function of the same class?

I don't believe you can do this.  The member function must be called
with a 'this' pointer, which the operating system will not be able to
supply.

>class A {
>	...
>	f();
>	timeout();
>};

>A::f()
>{
>	::signal(SIGALRM, timeout);
>	 ...
>}

The second paramater to signal() is of type "pointer to function taking
one int parameter, returning void".  The type of "timeout" is "pointer
to member function of A with no parameters, returning int".  This is a
type mismatch, and you should have gotten a compile-time error at the
call to signal().

It should be ok if timeout is a static member function of the right type:
	class A { ... static void timeout(int); ... };
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

fkho@watdragon.waterloo.edu (Frederick K. Ho) (04/25/91)

Hello,
Here's the summary of responses I have received from the net regarding
my question on using UNIX signal in C++. I thank all who responsed,
I am grateful to you all. As suggested, I am now making my member
function timeout() and variable "to" static in class A. Although it's
not an elegant solution but it serves my purpose right now since I
will not have more than one instantiation of the class A object. 

If anyone has a better solution, I would like to hear from you in how you
do it. Thank you again.

	//fred
	U. of Waterloo

In article <1991Apr22.194302.17795@watdragon.waterloo.edu> you write:
|> Here's what I did:
|> 
|> class A
|> {
|> private:
|> 	int	to;
|> public:
|> 	A();
|> 	~A();
|> 	f();
|> 	timeout();
|> };
|> 
|> A::timeout()
|> {
|> 	to = 1;
|> }
|> 
|> A::f()
|> {
|> 	// register the signal
|> 	::signal(SIGALRM, timeout);
|> 
|> 	 ...
|> }
|> 
|> 
|> Has I done anything wrong?
|> 

From pat%bnrmtl.UUCP@Larry.McRCIM.McGill.EDU Mon Apr 22 17:02:46 1991

Yes.  With a good set of system header files, this should not
even compile.  If I remember correctly, the second parameter
to signal() is a function taking an int argument (the signal
number) and returning nothing.  Something like this:

typedef void handler( int );
extern handler signal( int, handler );

(Caveats: I may have remembered this incorrectly, and it may
be different on your system.  Anyway, the gist is surely
correct.)

You, however, are passing a member function as the second
argument to signal().  This is a beast of an entirely different
colour, and it just won't work (For starters, how would your
timeout() know which object it should modify?).

One solution would be to make to and timeout static members
(one instance of each, rather than one per object).  Something like:

class A {
	...
	static int to;
	static void timeout( int );
};

A::timeout( int ) { to = 1; }

Static members (both data and functions) behave just like
normal data objects and functions declared outside of classes,
except for the the scoping rules and such like, so this 
should work.

-- 
Patrick Smith      Bell-Northern Research, Montreal, Canada
(514) 765-7914   bnrmtl!pat@larry.mcrcim.mcgill.edu   patrick@bnr.ca
These are my opinions, not facts; BNR may or may not agree with them.

===================================
From peter@csg.uwaterloo.ca Mon Apr 22 19:18:50 1991

In article <1991Apr22.194302.17795@watdragon.waterloo.edu> you write:

I'm pretty sure you can't pass the address of a member function to signal.
The documentation for signal should tell you.

Peter

===================================
From ken@csis.dit.csiro.au Tue Apr 23 03:02:24 1991

Since signal handlers must be non-member functions, how would you make
sure a member function is called with the correct "this"? One way out
is to have a non-member function in between.

===================================
From torda@igc.ethz.ch Tue Apr 23 03:03:14 1991

You don't say what machine or compiler, but have you tried

        ::signal (SIGALRM, A::timeout)

?
I had some more luck giving a more qualified name.
Didn't understand it, but it helped on a sparc with OS 4.1 and
SunC++.
Good luck.

--
Andrew Torda, ETH, Zurich

===================================
From olseno@cs.glasgow.ac.uk Tue Apr 23 11:51:54 1991

All member functions, unless they are static, expects the first argument
to be a pointer ('this') to the variables of the class, in your case 'to'.
This argument is implicitly included and one normally does not need to know 
it exists. I.e. A::timeout() looks like 

A::timeout( A * this )
{
       this->to = 1;
}

and in

main() {
  A a;
  a.timeout();
}

is compiled as
  timeout( &a );

 In your case, on the signal, execution is transferred to 
A::timeout(), but the argument this is not supplied, and hence this 
points to an arbitrary location and you get a bus error.

-----------------------------------------------------
Oystein Haug Olsen, Dept. of Electronics Engineering,
Univ. of Glasgow, Glasgow G12 8QQ, U.K.
JANET:  olseno@uk.ac.glasgow.cs    USENET:   olseno@cs.glasgow.uucp
BITNET: olseno%dcs.glasgow@UKACRL
ARPA:	olseno%glasgow.dcs@nsfnet-relay.ac.uk

===================================
From @yonge.csri.toronto.edu:tom@scocan Tue Apr 23 16:11:03 1991

You've done something wrong.  When the operating system invokes the
signal handler, it does not set up a "this" pointer, the first argument
is the signal (int sig).  You cannot directly register member functions
with the signal routine, you have to put a wrapper around it.

Tom Kelly  (416) 922-1937
SCO Canada, Inc. (formerly HCR) 130 Bloor St. W., Toronto, Ontario, Canada
{utzoo, utcsri, uunet}!scocan!tom or tom@sco.com

===================================
From ahodgson@hstbme.mit.edu Tue Apr 23 16:54:31 1991

I think the problem is that ::signal never gets the "this" pointer and
therefore can't call timeout properly (all member functions ALWAYS need
to be called in the context of an existing object).  One possible
approach is to use static member functions and variables:

class A
	{
	static to;
	static timeout() {  to = 1; }
	...
	}

::signal( ALARM, A::timeout );

A::timeout is well-defined and can be called even if no objects of type
A exist.  If you intend the message to be received by a particular object
of type A, you must define another static variable as a pointer to an
object of type A and send the appropriate message to it in timeout.

Hope this helps.

Tony Hodgson
ahodgson@hstbme.mit.edu

============================================
From cline@cheetah.ece.clarkson.edu Wed Apr 24 02:02:41 1991

The address of `timeout()' is a pointer-to-member-fn, not a ptr-to-fn.
The difference is easy to see by asking this question: which A *object*
should be the receipient of the `timeout()' message from signal()?
Since ::signal() requires a ptr-to-fn, you must create a top-level (file-
scope) fn that calls `timeout()' on the proper A object.

Marshall Cline
Keeper of the Borland C++ Bug Report

PS: If your company is interested in on-site C++/OOD training, drop me a line!
--
Marshall Cline / Asst.Prof / ECE Dept / Clarkson Univ / Potsdam, NY 13676
cline@sun.soe.clarkson.edu / Bitnet:BH0W@CLUTX / uunet!clutx.clarkson.edu!bh0w
Voice: 315-268-3868 / Secretary: 315-268-6511 / FAX: 315-268-7600

============================================
From vaughan%cadillac.cad.mcc.com@mcc.com Wed Apr 24 14:25:28 1991

You would have to use a static member function or a non-member
function. You noticed that the this pointer is corrupt, but think
about it--where is the this pointer coming from?  (answer, nowhere)


-- 
Internet:  fkho@watdragon.waterloo.{edu|ca}
UUCP:	   {ihnp4,decvax,uunet,utai, ...}!watmath!watdragon!fkho
Bitnet:	   fkho@water.BITNET, fkho@water.uwaterloo.ca