Replies: 3 comments 4 replies
-
I think it's possible you're encountering deadlock due to pipe buffer limits. Possibly you'll find some of the content here that was harvested from recent issues and discussions to be of interest. Some of us have been working on documentation for process management recently and there is a PR for it here -- it's based on the notes I linked earlier. That's not in rendered form but may be you'll find it to be of interest. |
Beta Was this translation helpful? Give feedback.
-
@nstgc Do you have I have the following example code working: (def cat (os/spawn ["cat"] :p {:in :pipe}))
(def buf (buffer/new-filled 14833896))
(:write (cat :in) buf)
(os/proc-close cat) The key being that if you have pipes for input and output, you have to keep in mind that the OS has a buffer limitation on how much data can be in a pipe that a process hasn't read off. If you write into the input and the process fails to read it you'll lose the capability to write to it's input until it reads it out. If the program writes to it's output and you have a custom pipe for it, it will block on writing if you fail to read it's output. What @sogaiu linked details some of this, but in general, you must pump the output pipes during your writes. The easiest way is with |
Beta Was this translation helpful? Give feedback.
-
It's not too hard to consume the output side of the pipe in your own process. It sounds like you understand the issue, but here's a more minimal example: # on my system, at least
(def pipe-buffer-size (* 1024 64))
(def proc (os/spawn ["cat"] :p {:in :pipe :out :pipe}))
(def buf (buffer/new-filled (+ 1 pipe-buffer-size)))
(ev/write (proc :in) buf)
(ev/close (proc :in))
(os/proc-wait proc) Once We can't just So we need to read (def pipe-buffer-size (* 1024 64))
(def proc (os/spawn ["cat"] :p {:in :pipe :out :pipe}))
(def buf (buffer/new-filled (+ 1 pipe-buffer-size)))
(ev/write (proc :in) buf)
(ev/close (proc :in))
(def output (ev/read (proc :out) :all))
(os/proc-wait proc) Because we never get to the So we want to do both "at the same time." Which we can do like this: (def pipe-buffer-size (* 1024 64))
(def proc (os/spawn ["cat"] :p {:in :pipe :out :pipe}))
(def output-chan (ev/chan))
(def read-fiber (ev/spawn
(ev/give output-chan (ev/read (proc :out) :all))))
(def write-fiber (ev/spawn
(def buf (buffer/new-filled (+ 1 pipe-buffer-size)))
(ev/write (proc :in) buf)
(ev/close (proc :in))))
(os/proc-wait proc)
(pp (length (ev/take output-chan))) We use Finally we pull the value off of the channel in the main process. (I don't think it matters what order we do You can also do this more concisely with (def pipe-buffer-size (* 1024 64))
(def proc (os/spawn ["cat"] :p {:in :pipe :out :pipe}))
(def [output _] (ev/gather
(ev/read (proc :out) :all)
(do
(def buf (buffer/new-filled (+ 1 pipe-buffer-size)))
(ev/write (proc :in) buf)
(ev/close (proc :in)))))
(os/proc-wait proc)
(pp (length output)) (The Edit: oh yeah, as @llmII points out, in the case that you only have one subprocess like this, you can use your main fiber as your "reader fiber." You don't actually need to move that to work to a separate fiber. Even simpler: (def pipe-buffer-size (* 1024 64))
(def proc (os/spawn ["cat"] :p {:in :pipe :out :pipe}))
(ev/spawn
(def buf (buffer/new-filled (+ 1 pipe-buffer-size)))
(ev/write (proc :in) buf)
(ev/close (proc :in)))
(pp (length (ev/read (proc :out) :all)))
(os/proc-wait proc) (Now it is important to do your |
Beta Was this translation helpful? Give feedback.
-
I have a process started with
(def cat (spawn ["cat"] :p {:in :pipe}))
and am writing to it with(:write (cat :in) data)
with(length data)
returning 14833896. It seems to be hanging: it prints the file's contents (binary) to the terminal and then stops.When I try this with something smaller, such as
"hello world"
it works as expected.Is there a maximum data size for
ev/write
?Note:
cat
is meant as a minimal working example, and the actual process I care about iszstd
which behaves the same way in that small inputs work as expected and large ones hang without any apparent work being done.Beta Was this translation helpful? Give feedback.
All reactions