Closing stdin for sub process

Started by rrq, June 07, 2014, 06:46:26 AM

Previous topic - Next topic

rrq

I have difficulty in closing stdin for a sub process using (process ..).

The code snippet is:
; 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?

rrq

#1
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:
(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

#2
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 (process ..) did that automatically.

TedWalther

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



(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:



(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,



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

#4
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.



(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.

rrq

#5
The latter function seems to have lost the expression
 (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

#6
Thanks for the answer

https://www.gclubtg.com/">บาคาร่าออนไลน์