www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Signal and slot trouble

reply Peter Federighi <pfederighi yahoo.com> writes:
So, I've been trying to come up with an nice way of dealing with POSIX/Linux
signals when I discovered std.signals.  It looked cool, and while it doesn't
provide exactly what I want to do (since I have to use global functions in
order to use sigaction), it's nice enough.  So here's a simplified form of
what I'm trying to do (it doesn't actually do anything).  It compiles fine,
but segfaults on the connect call.

Any ideas?
Thank you,
- Peter

import std.signals;
import std.stdio;

class SignalForwarder
    {
    mixin Signal!(int);
    }

SignalForwarder sigWinchSignal;	// Window size change signal
SignalForwarder sigAlrmSignal;	// Timer alarm signal

void main()
    {
    SigWinchHandler winch;
    SigAlrmHandler alrm;

    // put sigaction code here

    sigWinchSignal.connect(&winch.handler);
    sigAlrmSignal.connect(&alrm.handler);

    // do something here
    }

// the functions that get called via sigaction
void sigWinch(int signal)
    {
    sigWinchSignal.emit(signal);
    }

void sigAlrm(int signal)
    {
    sigAlrmSignal.emit(signal);
    }

// perhaps one of many functions I want called when a signal is raised
class SigWinchHandler
    {
    void handler(int signal)
	{
	writeln("WINCH");
	}
    }

class SigAlrmHandler
    {
    void handler(int signal)
	{
	writeln("ALRM");
	}
    }
Nov 21 2010
next sibling parent div0 <div0 sourceforge.net> writes:
This is just a random stab in the dark, but my guess is that std.signals 
hasn't been updated since the changes that make global vars live in TLS.

Try

__gshared SignalForwarder sigWinchSignal;
__gshared SignalForwarder sigAlrmSignal;


On 21/11/2010 08:05, Peter Federighi wrote:
 So, I've been trying to come up with an nice way of dealing with POSIX/Linux
 signals when I discovered std.signals.  It looked cool, and while it doesn't
 provide exactly what I want to do (since I have to use global functions in
 order to use sigaction), it's nice enough.  So here's a simplified form of
 what I'm trying to do (it doesn't actually do anything).  It compiles fine,
 but segfaults on the connect call.

 Any ideas?
 Thank you,
 - Peter

 import std.signals;
 import std.stdio;

 class SignalForwarder
      {
      mixin Signal!(int);
      }

 SignalForwarder sigWinchSignal;	// Window size change signal
 SignalForwarder sigAlrmSignal;	// Timer alarm signal

 void main()
      {
      SigWinchHandler winch;
      SigAlrmHandler alrm;

      // put sigaction code here

      sigWinchSignal.connect(&winch.handler);
      sigAlrmSignal.connect(&alrm.handler);

      // do something here
      }

 // the functions that get called via sigaction
 void sigWinch(int signal)
      {
      sigWinchSignal.emit(signal);
      }

 void sigAlrm(int signal)
      {
      sigAlrmSignal.emit(signal);
      }

 // perhaps one of many functions I want called when a signal is raised
 class SigWinchHandler
      {
      void handler(int signal)
 	{
 	writeln("WINCH");
 	}
      }

 class SigAlrmHandler
      {
      void handler(int signal)
 	{
 	writeln("ALRM");
 	}
      }

-- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Nov 21 2010
prev sibling next sibling parent reply "Johannes Pfau" <spam example.com> writes:
Am 21.11.2010, 09:05 Uhr, schrieb Peter Federighi <pfederighi yahoo.com>:

     SigWinchHandler winch;
     SigAlrmHandler alrm;

     // put sigaction code here

     sigWinchSignal.connect(&winch.handler);
     sigAlrmSignal.connect(&alrm.handler);

 // perhaps one of many functions I want called when a signal is raised
 class SigWinchHandler
     {
     void handler(int signal)
 	{
 	writeln("WINCH");
 	}
     }

with new. In your main function "SigWinchHandler winch;" just sets winch to null and in the connect call you access winch.handler which causes the crash. What you need to do is "SigWinchHandler winch = new SigWinchHandler();" and the same for SigAlrmHandler. -- Johannes Pfau
Nov 21 2010
parent Peter Federighi <pfederighi yahoo.com> writes:
From div0:
This is just a random stab in the dark, but my guess is that std.signals
hasn't been updated since the changes that make global vars live in TLS.

Try

__gshared SignalForwarder sigWinchSignal;
__gshared SignalForwarder sigAlrmSignal;


From Johannes Pfau:
SigWinchHandler is a class, so you have to create instances of the class
with new. In your main function "SigWinchHandler winch;" just sets winch
to null and in the connect call you access winch.handler which causes the
crash. What you need to do is "SigWinchHandler winch = new
SigWinchHandler();" and the same for SigAlrmHandler.



I've tried both of these things and neither work, nor do they work together.  Is
it because I'm trying to declare global instances of a class and then connect
things to it?  Does D make the object static or something?  I've tried the
example
from the Digital Mars website and it works, but nothing in it was declared
global.

Is there another (hopefully better) solution for catching C style signals in D?
Is there another way to program a timer and find out if the terminal size has
changed without having to use polling?

Thank you for your help,
- Peter
Nov 21 2010
prev sibling parent reply Peter Federighi <pfederighi yahoo.com> writes:
Ahh...  My ignorance is showing again.

So, on the thought that the global declaration of the class just creates an
instance and doesn't actually allocate it in memory, I added lines to main to
'new' them.  It works fine now.  I guess I'll have to add some error handling to
make sure the classes actually exist instead of just using them.

I'd still like to know if there's a better way/native way to trap C style
signals
in D.  Or is there a D way of programming a timer and finding terminal window
size
changes?

On a side note:
What's with D not actually allocating a class in a declaration?  Isn't that
syntactically odd?  If I say 'int x' , I get an int.  I don't have to say 'int
x =
new int'.  So, it seems logical to me that I should be able to say 'MyClass mc'
and get a MyClass.

Thank you for the help,
- Peter
Nov 21 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Peter Federighi:

 So, on the thought that the global declaration of the class just creates an
 instance and doesn't actually allocate it in memory,

In code like: class Foo {} void main() { Foo x; } x isn't an instance, it is just an empty (null) reference to class instances.
 What's with D not actually allocating a class in a declaration?  Isn't that
 syntactically odd?  If I say 'int x' , I get an int.  I don't have to say 'int
x =
 new int'.  So, it seems logical to me that I should be able to say 'MyClass mc'
 and get a MyClass.

In D structs are values, so in this code x is an instance of Foo, on the stack: Struct Foo {} void main() { Foo x; } But in D objects are reference types, they are always composed by a reference that points to the instance (as in Java) that is often on the heap. To avoid other bugs/troubles, I suggest you to read the basics about D from the site. Bye, bearophile
Nov 21 2010
prev sibling parent "Johannes Pfau" <spam example.com> writes:
Am 21.11.2010, 19:47 Uhr, schrieb Peter Federighi <pfederighi yahoo.com>:

 I'd still like to know if there's a better way/native way to trap C  
 style signals
 in D.  Or is there a D way of programming a timer and finding terminal  
 window size
 changes?

I don't think there are any D libraries to handle posix signals. Posix signals are a pita. In theory all functions you call in posix signal handlers must be signal safe and the requirements for that are very strict. Allocating memory in a signal handler is not safe for example. In practice, Linux for example is way more tolerant that the posix specification, so you often won't experience any problems with faulty signal handlers. Problems start to appear when you port to different OS which might be less forgiving. And as you're relying on unspecified features, a future update in kernel / external libraries could break your application. (http://en.wikipedia.org/wiki/Signal_(computing)#Risks) Because of these issues many people try to avoid signals whenever possible. If signals are needed the recommendation often is to use synchronous signal handling where all those issues don't exist. The key to synchronous signal handling is the sigwait function(http://linux.die.net/man/3/sigwait) but it blocks one thread all the time. Other possible solutions: signals can be managed with libev. I guess it uses synchronous signal handling internally, but it allows you to wait for an io event, signal, and other things in one thread. libev also has timers. I've also seen an timer implementation which uses a mutex and condition variables with timeouts to simulate a timer. Works without signals or any special system support, but I don't know of an implementation for D. The simplest(and least effective) possibility is to use a loop, Thread.sleep() and polling //Pseudo code, functions might have other names ;-) Size lastSize; while(true) { auto size = getWindowSize(); if(size != lastSize) ... Thread.sleep(1000); } -- Johannes Pfau
Nov 22 2010