Closing stdin for sub process

Q&A's, tips, howto's
Locked
ralph.ronnquist
Posts: 228
Joined: Mon Jun 02, 2014 1:40 am
Location: Melbourne, Australia

Closing stdin for sub process

Post by ralph.ronnquist »

I have difficulty in closing stdin for a sub process using (process ..).
The code snippet is:

Code: Select all

; Spawn a reader for emptying sub process stdout as my stdout
(setq buffer nil)
(map set '(myin subout) (pipe))
(fork (begin (close subout) (while (read myin buffer 1000) (print buffer))))
(close myin)

(map set '(subin myout) (pipe))
(process "./myscript.zsh " subin subout)
(close subin)(close subout)
...
(close myout)
I would like that last "close" to close the stdin for the myscript.zsh sub process, but this doesn't seem to happen.

Possibly the issue is that the process spawned by the "process" function actually has inherited a writing end of the pipe (it's "dup" of "myout"), and that remains open. If so, how do I close it? Or have I missed something?

ralph.ronnquist
Posts: 228
Joined: Mon Jun 02, 2014 1:40 am
Location: Melbourne, Australia

Re: Closing stdin for sub process

Post by ralph.ronnquist »

A little bit later, I realized I could wrap the "process" into a fork, and there close "myout" before spawning the sub process. Thusly wrapped:

Code: Select all

(fork (begin (close myout) (process ...)))
It kind of validates my theory that "myout" indeed is open for the sub process.

Perhaps it'd be sensible to revise the "process" method to in some way allow that pipe end closing to happen? Maybe even that the implementation could actually close all open file descriptors except the given ones on the execing-fork before exec-ing (that's me making assumptions about the implementation without having more than peeped at it :-))?

werelax
Posts: 1
Joined: Mon Nov 23, 2015 12:38 pm

Re: Closing stdin for sub process

Post by werelax »

Just had this problem and didn't know what to do. Thanks for posting your solution!

Still, it is a bit cumbersome. Would be great if

Code: Select all

(process ..)
did that automatically.

TedWalther
Posts: 608
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC
Contact:

Re: Closing stdin for sub process

Post by TedWalther »

I think I'm having the same problem. Here is the code:

Code: Select all

(define (remote-script remconnect remscript)
  (map set '(inloc outrem) (pipe))
  (map set '(inrem outloc) (pipe))
  (set 'pid (process remconnect inrem outrem))

  (write outloc remscript)
  (close outloc)
  (close inrem)
  (close outrem)

  (while (set 'p (peek inloc))
    (sleep 500)
    (print "peek" p " " (read inloc buf 128) " " buf))

  (close inrem)
  (destroy pid)
)
An example of what I'm trying to do with it:

Code: Select all

(remote-script "ssh mybox sh" "df -h")
That sample would log into my box and check disk usage.

However, when I do that, it hangs. If I run that from the command line,

Code: Select all

echo df -h | ssh mybox sh
It works; it runs the command and exits and returns to shell.

When I use (process) it never detects that the ssh program has ended.

I am using newLisp 10.6.2 on Debian Linux.

This problem happens also if I don't close the pipe ends.

Since I need the output of the command, I'm reluctant to add the extra complexity of spawn/send.
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence. Nine months later, they left with a baby named newLISP. The women of the ivory towers wept and wailed. "Abomination!" they cried.

TedWalther
Posts: 608
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC
Contact:

Re: Closing stdin for sub process

Post by TedWalther »

I finally made it work using (wait-pid -1 nil), the non-blocking version of waitpid. Still, I'm puzzled that when process exits, the file descriptors aren't closed off and I don't get EOF when I'm finished reading from a dead process. Even when I do the waitpid so the process is reaped, the file handles are treated as valid.

Code: Select all

(define (remote-script remconnect remscript)
  (map set '(inloc outrem) (pipe))
  (map set '(inrem outloc) (pipe))
  (set 'pid (process remconnect inrem outrem))

  (write outloc remscript)
  (close outloc)

  (while (or (> (set 'p (peek inloc))) pid)
    (when (= pid (first (wait-pid -1 nil)))
      (set 'pid nil))
    (when (> p)
      (read inloc buf 4096)
      (print buf))
    (sleep 50)))

(define script-text {df -h; echo hi there;})
(remote-script "/usr/bin/ssh mybox sh" script-text)
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence. Nine months later, they left with a baby named newLISP. The women of the ivory towers wept and wailed. "Abomination!" they cried.

ralph.ronnquist
Posts: 228
Joined: Mon Jun 02, 2014 1:40 am
Location: Melbourne, Australia

Re: Closing stdin for sub process

Post by ralph.ronnquist »

The latter function seems to have lost the expression

Code: Select all

(close outrem)
that should follow the process expression.
Without that, the pipe is of course held open by the parent process having an open write-end.

By the way, your first function works fine for me if you skip using peek and just call read in the while condition. According to the manual, peek only returns nil for invalid file descriptors, so probably a pipe with EOF is considered valid.

abaddon1234
Posts: 21
Joined: Mon Sep 14, 2015 3:09 am

Re: Closing stdin for sub process

Post by abaddon1234 »


Locked