Abort a system call

With parts of other pieces today on the reflector, I assembled this

--------
pid = Process.fork do
  exec($decoder, $bitstreamPath, $yuvOutputPath)
end

trap "SIGINT", proc{ Process.kill("SIGINT", pid); print "^C
was pressed. Process id #{pid}\n" }

Process.waitpid(pid)
--------

The trap gets executed, meaning that I get the output of the
print, during the execution of my program, and the pid
matches the one from the process status list. However the
first part (Process.kill("SIGINT", pid):wink: is not executed
correctly, or at least does not do what I expected, killing
the process. Is there another way to kill a process from
Ruby? Or do I need another signal # instead of "SIGINT"
there? No clue...

For those having similar problems, I just solved it by

trap "INT", proc{ Process.kill(9, pid) }

so using a hard kill.

If people have more elegant ways of solving this, let me know!

CU

B

Here is what I think is going on. Ruby sets up the signal handler so
that some system call will resume after the interrupt instead of
returning with EINTR:

from ruby-signal in signal.c:

#if defined(SA_RESTART)
    /* All other signals but VTALRM shall restart restartable syscall
       VTALRM will cause EINTR to syscall if interrupted.
    */
    if (signum != SIGVTALRM) {
        sigact.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */
    }
#endif

And from man sigaction:
SA_RESTART
                     Provide behaviour compatible with BSD signal
semantics by
                     making certain system calls restartable across
signals.

That is why Process.waitpid(pid) doesn't return until your decoder
process dies. Maybe Perl doesn't do that and it would explain the
difference of behavior.

Second, it seems that your decoder process doesn't terminate on a
SIGINT. Maybe you should send a SIGTERM, to be a little more graceful
than SIGKILL (9).

Hope it helps,
Guillaume.

PS: people in the know, please correct me if I got it wrong about the
way the signals are handled.

···

On Tue, 2005-07-05 at 21:18 +0900, Masschelein Bart wrote:

>
> With parts of other pieces today on the reflector, I assembled this
>
> --------
> pid = Process.fork do
> exec($decoder, $bitstreamPath, $yuvOutputPath)
> end
>
> trap "SIGINT", proc{ Process.kill("SIGINT", pid); print "^C
> was pressed. Process id #{pid}\n" }
>
> Process.waitpid(pid)
> --------
>
> The trap gets executed, meaning that I get the output of the
> print, during the execution of my program, and the pid
> matches the one from the process status list. However the
> first part (Process.kill("SIGINT", pid):wink: is not executed
> correctly, or at least does not do what I expected, killing
> the process. Is there another way to kill a process from
> Ruby? Or do I need another signal # instead of "SIGINT"
> there? No clue...
>

For those having similar problems, I just solved it by

trap "INT", proc{ Process.kill(9, pid) }

so using a hard kill.

If people have more elegant ways of solving this, let me know!