• Expect question: How to force return from interact on child death signa

    From Kenny McCormack@21:1/5 to All on Tue Jul 18 17:52:10 2023
    Consider the code below. Note: Yes, I know this is doing everything the
    hard way, but be assured that that is the overall goal - in the context of
    the larger (actual) issue. Yes, if I do things the easy way, it will "just work".

    --- Cut Here ---
    #!/usr/bin/expect --
    # This works, but it still seems like there ought to be a better way!
    trap { puts "In CHLD handler, wait returns: [wait]";incr cflag } CHLD
    spawn -pty
    set tty $spawn_out(slave,name)
    puts "Pid of nl is: [exec nl < $tty > $tty 2> $tty &]"
    set cflag 0
    interact timeout 5 { if $cflag return } ~
    puts "Bye bye!"
    --- Cut Here ---

    When I run the above script, I interact with "nl" for a bit, then press ^D
    to cause "nl" to exit.

    The basic problem is that, when you do things normally, interact will return when the spawned process dies. That's good. But, when we do it the other
    way (using "spawn -pty" instead of a normal "spawn"), the child process
    dying does not cause interact to exit. That is, unless we take steps such
    as shown above.

    Notes:
    1) I am aware that if I do "close -slave" before the interact, then it
    will work "as expected" - that is, it will exit (return) immediately
    when the child process dies. But, of course, doing that would
    defe
  • From heinrichmartin@21:1/5 to Kenny McCormack on Thu Jul 20 23:39:17 2023
    On Tuesday, July 18, 2023 at 7:52:14 PM UTC+2, Kenny McCormack wrote:
    Consider the code below. Note: Yes, I know this is doing everything the
    hard way, but be assured that that is the overall goal - in the context of the larger (actual) issue. Yes, if I do things the easy way, it will "just work".

    --- Cut Here ---
    #!/usr/bin/expect --
    # This works, but it still seems like there ought to be a better way!
    trap { puts "In CHLD handler, wait returns: [wait]";incr cflag } CHLD

    I guess you want to use "Inside a SIGCHLD handler, it is possible to wait for any spawned process by using the spawn id -1." to be more robust in complex scenarios.

    spawn -pty
    set tty $spawn_out(slave,name)
    puts "Pid of nl is: [exec nl < $tty > $tty 2> $tty &]"
    set cflag 0
    interact timeout 5 { if $cflag return } ~

    Have you tried to debug whether pattern eof is detected? You could define a non-default eof pattern or investigate exp_internal.

    puts "Bye bye!"
    --- Cut Here ---

    When I run the above script, I interact with "nl" for a bit, then press ^D to cause "nl" to exit.

    Your problem is _not_ that the child process does not exit, is it?
    Anyway, reviewing stty settings could help.

    The basic problem is that, when you do things normally, interact will return when the spawned process dies. That's good. But, when we do it the other
    way (using "spawn -pty" instead of a normal "spawn"), the child process dying does not cause interact to exit. That is, unless we take steps such
    as shown above.

    Notes:
    1) I am aware that if I do "close -slave" before the interact, then it
    will work "as expected" - that is, it will exit (return) immediately
    when the child process dies. But, of course, doing that would
    defeat the actual purpose.
    2) What I really want is something that I can do in the CHLD handler
    that will cause the interact to immediately exit (return). Is
    there a way? Using timeout is a kludge, of course.

    Have you tried close inside the handler?

    3) "nl" is a standard Unix tool - it was just what I happened to be
    testing with.

    --
    The randomly chosen signature file that would have appeared here is more than 4
    lines long. As such, it violates one or more Usenet RFCs. In order to remain in compliance with said RFCs, the actual sig can be found at the following URL:
    http://user.xmission.com/~gazelle/Sigs/Noam

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to [email protected] on Fri Jul 21 12:41:24 2023
    In article <[email protected]>, heinrichmartin <[email protected]> wrote:

    Thanks for your response. I think, though, that most of your questions
    have already been anticipated, and I give responses below.

    I guess you want to use "Inside a SIGCHLD handler, it is possible to wait
    for any spawned process by using the spawn id -1." to be more robust in >complex scenarios.

    Not really relevant to the thread, but interesting. Actually, a better
    overall solution is just to have the handler do: incr cflag
    and let the regular inline code take things from there. I.e., do the wait inline (after returning from the "interact") instead of in the handler.


    Have you tried to debug whether pattern eof is detected? You could define a >non-default eof pattern or investigate exp_internal.

    I haven't actually tried it, but I had read about "eof". From what I can
    tell, it wouldn't help, because "eof" is caught by default anyway, so if
    "eof" were being triggered, I'd already have a solution to the problem.

    I'm not familiar with exp_internal. What is that?

    puts "Bye bye!"
    --- Cut Here ---

    When I run the above script, I interact with "nl" for a bit, then press ^D >> to cause "nl" to exit.

    Your problem is _not_ that the child process does not exit, is it?

    No. I can tell tha the child process has exited (and gone zombie,
    unless/until I do a "wait").

    Anyway, reviewing stty settings could help.

    Don't think that is relevant.

    Have you tried close inside the handler?

    Well, as I indicated in the OP, doing a close would defeat the overall
    purpose. As I said, doing "close -slave" does make things work "normally",
    but again, defeats the purpose.

    Just to clarify, the overall purpose is this: I want to run multiple
    processes in a loop. Normally, the model is:

    1) spawn myProcess
    2) interact
    (interact runs, and returns when the process exits)
    3) wait (to de-zombie)
    4) goto 1

    I want to change the model to:

    1) spawn -pty
    2) exec my program, connecting it to the tty (details in original code)
    3) interact
    (interact runs, but, unfortunately, does not return when the process exits)
    (but, using the CHLD hack, we can "fake" that result)
    4) wait (to de-zombie)
    5) goto 2

    The point being that I want to spawn the pty once, and keep it open
    thereafter. The reasons for *why* I want to do this are beyond the scope
    of this article.

    --
    The randomly chosen signature file that would have appeared here is more than 4 lines long. As such, it violates one or more Usenet RFCs. In order to remain in compliance with said RFCs, the actual sig can be found at the following URL:
    http://user.xmission.com/~gazelle/Sigs/God

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From heinrichmartin@21:1/5 to Kenny McCormack on Sun Jul 23 04:39:31 2023
    On Friday, July 21, 2023 at 2:41:29 PM UTC+2, Kenny McCormack wrote:
    In article <[email protected]>, heinrichmartin wrote:

    Thanks for your response. I think, though, that most of your questions
    have already been anticipated, and I give responses below.
    I guess you want to use "Inside a SIGCHLD handler, it is possible to wait >for any spawned process by using the spawn id -1." to be more robust in >complex scenarios.
    Not really relevant to the thread, but interesting. Actually, a better overall solution is just to have the handler do: incr cflag
    and let the regular inline code take things from there. I.e., do the wait inline (after returning from the "interact") instead of in the handler.

    Have you tried to debug whether pattern eof is detected? You could define a >non-default eof pattern or investigate exp_internal.
    I haven't actually tried it, but I had read about "eof". From what I can tell, it wouldn't help, because "eof" is caught by default anyway, so if "eof" were being triggered, I'd already have a solution to the problem.

    I'm not familiar with exp_internal. What is that?

    It is logging Expect's internals when matching patterns. You can/should write it to a file (man expect: "exp_internal -f exp_internal.dbg 0") and inspect that afterwards.
    The format is quite noisy, but one can get used to it. I have a language file for source-highlight that I can share as-is.

    puts "Bye bye!"
    --- Cut Here ---

    When I run the above script, I interact with "nl" for a bit, then press ^D
    to cause "nl" to exit.

    Your problem is _not_ that the child process does not exit, is it?
    No. I can tell tha the child process has exited (and gone zombie, unless/until I do a "wait").
    Anyway, reviewing stty settings could help.
    Don't think that is relevant.
    Have you tried close inside the handler?
    Well, as I indicated in the OP, doing a close would defeat the overall purpose. As I said, doing "close -slave" does make things work "normally", but again, defeats the purpose.

    I guess I have misread that.

    Just to clarify, the overall purpose is this: I want to run multiple processes in a loop. Normally, the model is:

    1) spawn myProcess
    2) interact
    (interact runs, and returns when the process exits)
    3) wait (to de-zombie)
    4) goto 1

    I want to change the model to:

    1) spawn -pty
    2) exec my program, connecting it to the tty (details in original code)
    3) interact
    (interact runs, but, unfortunately, does not return when the process exits) (but, using the CHLD hack, we can "fake" that result)
    4) wait (to de-zombie)
    5) goto 2

    The point being that I want to spawn the pty once, and keep it open thereafter. The reasons for *why* I want to do this are beyond the scope
    of this article.

    I am afraid that is none of my use cases. Therefore, I can just point to other options (unordered as they cross my mind):
    * use a worker shell instead of a pty (you might want to set stty -echo as well as a fancy unique prompt)
    * use Tcl channels in exec and spawn -open
    * use a wrapper script for the processes that print a unique token on exit

    HTH
    Martin

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)