Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Sending Signals / Keyboard Interrupts

by PyrexKidd (Monk)
on Jul 18, 2011 at 21:55 UTC ( [id://915292]=perlquestion: print w/replies, xml ) Need Help??

PyrexKidd has asked for the wisdom of the Perl Monks concerning the following question:

EDIT: Clarification

Ok, let me try to rephrase.

What is the best way to affect program behavior, using keyboard keys/commands/shortcuts/signals, without waiting for user input?

I would like to send keyboard interrupts to a running Perl process to cause it to perform certain functions midstream. For instance, I would like to press ^C and have it dump some information to the screen, I would like to press ^Z and have it dump some information to a file, etc.

To my thinking, it would be easiest to use signals to illicit this behavior from my program especially because it runs in the foreground of a terminal; I am not sure how to send these signals to the program using keyboard controls.
I could use the Linux command 'kill' (and the respective signal number) to send the signals to the process, or I could write a second program and use the Perl built-in 'kill' to send these signals, but this requires a second terminal (which may or may not be feasible) and requires knowing the PID of the Perl process (which is leas than ideal). Both of these solutions are less than ideal.

my problem is I can only send the interrupt signal via keyboard keys.
I assure you this is not what I meant... What I was trying to say is: I would like to send the signals via keyboard keys (or combination of keys), my problem is I don't know how.
{What you didn't get that from that sentence?!? I can imagine why... Can't you read minds?}

Perhaps signals aren't the best choice; I am open to other suggestions, but have no idea where to start other than completely rewriting my program using the POE framework...

Thanks for your understanding; I work for a help desk, so I totally understand how painful it can be when someone requests help and provides partial (or less than partial) information.


Original Post:

Hello Monks,
I am not sure exactly where this fits in the computer science universe, so I'm hoping you can help me.
Essentially, I would like to be able to send signals to a running Perl process to cause it to do things mid run.
This is not an event driven script and does not lend itself to be easily rewritten in POE. (My first thought.)
So my next thought is to use signals to affect program behavior; I only need a couple of events.

I understand how to trap signals in Perl, my trouble is with sending the signals. Ideally I would like to be able to press ^C and do something, then ^Z and do something else, my problem is I can only send the interrupt signal via keyboard keys. (as a last choice I can use `kill -* $PID` to send the required signals, but this seems like a poor choice.)
Maybe I need to rethink my whole approach. Any thoughts, suggestions, ideas, comments, criticisms, or jokes?

An overtly simplified version of what I am talking about follows:

#!/usr/bin/perl use strict; use warnings; $SIG{'HUP'} = \&hangup; $SIG{'INT'} = \&interrupt; $SIG{'KILL'} = \&kill; #create necessary vars. while (1){ #do main processing here } sub hangup { my $sig = shift; print "Got SIG$sig exiting"; exit 0; } sub interrupt { #do stuff here } sub kill { print "HaHa, can't kill me!\n"; }
you get the idea.

Replies are listed 'Best First'.
Re: Sending Signals / Keyboard Interrupts
by ikegami (Patriarch) on Jul 18, 2011 at 22:22 UTC

    as a last choice I can use `kill -* $PID` to send the required signals, but this seems like a poor choice.

    Are you perhaps looking for kill?

    my problem is I can only send the interrupt signal via keyboard keys.

    huh? You've proved that this isn't true in the very next sentence.

    Maybe I need to rethink my whole approach.

    This seems to be your question, but it can't be answered (well) since you didn't tell us what you are trying to achieve.

      deleted.
        Original content of parent

        Ok, let me try to rephrase.

        What is the best way to affect program behavior, using keyboard keys/commands/shortcuts/signals, without waiting for user input?

        I would like to send keyboard interrupts to a running Perl process to cause it to perform certain functions midstream. For instance, I would like to press ^C and have it dump some information to the screen, I would like to press ^Z and have it dump some information to a file, etc.

        To my thinking, it would be easiest to use signals to illicit this behavior from my program especially because it runs in the foreground of a terminal; I am not sure how to send these signals to the program using keyboard controls.
        I could use the Linux command 'kill' (and the respective signal number) to send the signals to the process, or I could write a second program and use the Perl built-in 'kill' to send these signals, but this requires a second terminal (which may or may not be feasible) and requires knowing the PID of the Perl process (which is leas than ideal). Both of these solutions are less than ideal.

        my problem is I can only send the interrupt signal via keyboard keys.
        I assure you this is not what I meant... What I was trying to say is: I would like to send the signals via keyboard keys (or combination of keys), my problem is I don't know how. {What you didn't get that?!? I can imagine why... Can't you read minds?}

        Perhaps signals aren't the best choice; I am open to other suggestions, but have no idea where to start other than completely rewriting my program using the POE framework...

        Thanks for your understanding; I work for a help desk, so I totally understand how painful it can be when someone requests help and provides partial (or less than partial) information.

        What is the best way to affect program behavior, using keyboard keys/commands/shortcuts/signals, without waiting for user input?

        Do wait for user input, just do your processing in a separate thread.

Re: Sending Signals / Keyboard Interrupts
by cdarke (Prior) on Jul 19, 2011 at 10:32 UTC
    On your Clarification post:

    You seem to understand that certain keyboard interrupts send signals, and that you can cause kill to raise them (not everyone does).

    You appear to be saying that you want to generate the keyboard interrupts from withing your program, and I don't understand why you can't just call the required function. Why do you need to invoke a signal to do it?
Re: Sending Signals / Keyboard Interrupts
by Marshall (Canon) on Jul 19, 2011 at 20:27 UTC
    I would recommend keeping things simple. One way to do this is to just poll periodically and check for some user input, if some key like CTL-Z has been hit, then do the command.

    The terminal starts out by default in the "Enter sends line", the "cooked" or canonical mode. This mode is nice as your program doesn't have to fiddle with any user editing of the line, etc. To get raw characters (like what vi does), you need "raw" or "non-canonical" mode. If you want to read a character if one is there, else keep going, you need non-blocking mode. The Term:ReadKey module has what you need.

    I would shy away from redefining CTL-C or other common control characters. This "it doesn't do what it normally would do" stuff can be a hassle and cause user confusion. I would try to pick some other key combinations that make sense to the application.

    While the use of signals is possible (and there are some "user defined" ones), this doesn't sound ideal. A polling solution works great as long as you poll often enough.

    Were you hung up because of not knowing how to use non-blocking and/or raw terminal mode? Or is there some other reason that polling doesn't work?

    The handling of signals that can occur asynchronously while your program is at any random point adds a significant layer of complexity. I would not head in that direction unless you really need to.

Re: Sending Signals / Keyboard Interrupts
by SuicideJunkie (Vicar) on Jul 19, 2011 at 13:57 UTC

    Sounds to me like you still want user input, but want a way to do it in a non-blocking way.

    Have you considered starting a second thread in your program? The second thread could do regular blocking reads from stdin and then use shared variables to control the flow of the main thread. It would be using sequences of keys (ending in CR) rather than key combinations, but from your description, it sounds like that would be fine.

    (See threads and threads::shared)

Re: Sending Signals / Keyboard Interrupts
by PyrexKidd (Monk) on Jul 20, 2011 at 23:20 UTC

    Here is an overly simplified version of what I am trying to accomplish:

    #!/usr/bin/perl use strict; use warnings; $SIG{'INT'} = \&print_var; my $i = 0; $i++ while 1; sub print_var { print $i . "\n"; }

    Obviously this code doesn't do anything useful;
    this is really a skeleton of what I would like to do.

    It sounds like Term::Readkey will be what I need. Assuming what I think 'non blocking way' means is correct, (I think it means allowing user input without stopping program execution) then yes this is what I want to do. (In fact I'm off to do some research on this very concept.)

    Re: The Threaded Method
    I'm not sure how to implement this, you seem to be telling me to fork my continual loop and then in the main program wait for the user input? Wouldn't I need to use signals to communicate with my forked process?
    Really I think my lack of experience with threaded applications really shows as I've only ever forked a Perl program into the background using the & operator from the CLI. While I don't think this is the method I will implement for this program, can you suggest some good resources to learn about threading?

    Gents, thanks for all your help, I really think you've pointed me in the right direction.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://915292]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (4)
As of 2024-04-25 13:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found