Closing stdin for sub process

Q&A's, tips, howto's

Closing stdin for sub process

Postby ralph.ronnquist » Sat Jun 07, 2014 1:46 pm

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: 202
Joined: Mon Jun 02, 2014 1:40 am
Location: Melbourne, Australia

Re: Closing stdin for sub process

Postby ralph.ronnquist » Sat Jun 07, 2014 2:21 pm

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 :-))?
ralph.ronnquist
 
Posts: 202
Joined: Mon Jun 02, 2014 1:40 am
Location: Melbourne, Australia

Re: Closing stdin for sub process

Postby werelax » Wed Nov 25, 2015 10:01 pm

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.
werelax
 
Posts: 1
Joined: Mon Nov 23, 2015 12:38 pm

Re: Closing stdin for sub process

Postby TedWalther » Sat Dec 05, 2015 12:07 pm

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: 605
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC

Re: Closing stdin for sub process

Postby TedWalther » Sun Dec 06, 2015 3:10 am

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.
TedWalther
 
Posts: 605
Joined: Mon Feb 05, 2007 1:04 am
Location: Abbotsford, BC

Re: Closing stdin for sub process

Postby ralph.ronnquist » Sun Dec 06, 2015 10:12 am

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.
ralph.ronnquist
 
Posts: 202
Joined: Mon Jun 02, 2014 1:40 am
Location: Melbourne, Australia

Re: Closing stdin for sub process

Postby abaddon1234 » Sat May 07, 2016 4:20 am

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


Return to newLISP in the real world

Who is online

Users browsing this forum: No registered users and 3 guests

cron