Comments (17)
joker.os/sh
, joker.os/sh-from
and joker.os/exec
are the only functions that spawn new processes. They are blocking and do not allow for fine-grained control over child processes. You can use go macro to run child processes in non-blocking way. However, there is no API to send signals to child processes. You may have to resort to using pgrep
and kill
for that, e.g.
(go
(pprint (joker.os/sh "joker" "sleep.joke"))) ;; start a child process
(joker.time/sleep 1000000000) ;; simulate i/o to let the goroutine a chance to start
(let [pgrep-out (:out (joker.os/sh "pgrep" "-P" (str (joker.os/pid)))) ;; find child pid by parent pid
child-pid-str (subs pgrep-out 0 (dec (count pgrep-out))) ;; delete trailing \n
]
(joker.os/sh "kill" child-pid-str))
from joker.
I wanted to emulate something like this in joker.
#!/bin/sh
cmd1 arg1 arg2 ... &
pid=$!
cmd2 arg1 arg2 ...
kill $pid
from joker.
I added two functions in start-kill-process
branch: joker.os/start-process
and joker.os/kill-process
. Usage example:
(let [pid1 (joker.os/start-process "/bin/sleep" "1000")
pid2 (joker.os/start-process "/bin/sleep" "1000")]
(joker.os/kill-process pid1)
(println "done!"))
@amano-kenji Do you think this will work? Would you be willing to build that branch locally and try it for your use case?
from joker.
I compiled and tested it. That seems to do the job, but what about control over stdout, stderr, stdin, and current working directory?
from joker.
I wonder if it'd make sense to enhance joker.os/exec
, or provide an alternate, that doesn't Wait
for the process to finish, but instead returns the underlying os.Process
object (perhaps among other things) returned by os.exec/Start()
?
That way, the features provided by joker.os/exec
to prepare a process would be available, with the flexibility of being able to manipulate the returned os.Process
object such as your proposed joker.os/kill-process
provides.
I think an alternate to joker.os/exec
, like joker.os/exec-nowait
, makes more sense at least to simplify the returned value, which wouldn't have to contain things that make sense only due to the current implementation calling os.Wait
.
from joker.
Yes, I think it makes sense. I was not sure how useful it would be to be able to set up stdin/out/err for processes that are started asynchronously and how this would behave when the process is killed by the parent program. I'll experiment with this on the weekend.
I also went for a simpler (perhaps too simple?) approach of returning a PID rather than a os.Process wrapper since os.Process can always be obtained by PID with os.FindProcess.
from joker.
I may want to redirect stdout and stderr to /dev/null and feed some input to stdin.
from joker.
@amano-kenji , @jcburley I made the change so that now joker.os/start-process
accepts the same arguments as exec
(and shares most of its implementation). Example:
(let [pid1 (joker.os/start-process "joker" {:args ["/Users/candid/sleep.joke"]
:stdout *out*})
pid2 (joker.os/start-process "/bin/sleep" {:args ["1000"]})]
(joker.time/sleep (* 5 joker.time/second))
(joker.os/kill-process pid1)
(println "done!"))
Please let me know what you think.
from joker.
That should do the job although being able to send other signals than TERM to a process is going to be useful.
from joker.
@amano-kenji Fair enough. I added signal
function (takes pid and signal as arguments). I also renamed start-process
to start
and kill-process
to kill
. Please give it a try and let me know what you think.
from joker.
I just tested. If I start
a process and kill
its PID in joker REPL, the PID becomes defunct until I quit REPL. After I quit REPL, the PID actually dies. Is this normal?
Also, it would be cool to have predefined SIGNALs for signal
function.
from joker.
@amano-kenji Zombie processes are sort of normal: https://www.baeldung.com/linux/clean-zombie-process
They appear if the parent process doesn't wait
on them after they finish execution. My initial implementation of joker.os/kill
did not wait on the process being killed. I changed that, so now joker.os/kill
waits after killing the process: baefcf5 This solves the issue with zombie processes (although I am not 100% it was a real issue).
As for predefined signals, they are platform specific. We would have to expose different set of constants on different platforms (at least on three officially supported platformes: Linux, macOS and Windows). I don't believe we do this anywhere else in Joker's codebase. @jcburley do you have any input on this (perhaps you've done this in your fork?)
from joker.
As for predefined signals, they are platform specific. We would have to expose different set of constants on different platforms (at least on three officially supported platformes: Linux, macOS and Windows). I don't believe we do this anywhere else in Joker's codebase. @jcburley do you have any input on this (perhaps you've done this in your fork?)
My fork's gostd
tool, which "wraps" much of the Go standard library for direct access via Joker code, is run as part of the build process for a specific target.
So it doesn't really handle this in any particularly sophisticated way, in that the constants and variables that get wrapped, for a specific Joker executable, are just whatever happen to apply to that particular target.
I.e. the Joker namespaces that get exposed, along with their contents, in a particular executable, depend on what makes sense for that executable's target. Things that are Mac-OS-specific will appear, as namespaces and/or entities within them, in a Joker executable built for the Mac OS platform, but not on one built for a Linux nor Windows platform.
Early on, I thought it might be possible to someday make gostd
smart enough to generate wrappers for all namespaces (packages in the Go standard library) and their contents, and use build tags and such to parallel how the Go standard library itself does.
But that seems very difficult, with little (if any) benefit, other than that my "fork" could then just be a source distribution without any need to run gostd
for a particular build, at least in the vanilla case of wrapping the Go standard library.
So I've punted that capability, which is Issue jcburley#10.
from joker.
@jcburley thank you for the input! Here is my attempt to add support for platform-dependent declarations (non-functions) in std library: 2db1f41
This means that, e.g. joker.os/SIGBUS
will be 0xa
on macOS and 0x7
on Linux and Windows. joker.os/SIGCHLD
will be 0x14
on macOS, 0x11
on Linux and won't exist on Windows.
This complicates build process a bit since now you have to generate std library for specific OS. Not sure how I feel about it... I guess it's useful to be able to write (joker.os/signal 1234 joker.os/SIGBUS)
and the right signal will be sent on macOS and Linux... @jcburley any thoughts on this?
from joker.
I guess the alternative to this would be to only define signals that have the same value across all platforms. Now that I look at it, most common/useful signals fall into that category (e.g. SIGKILL, SIGTERM, SIGABRT). So perhaps it makes sense to punt on platform-dependent declaration for now until there is a more compelling use case for it?
from joker.
It's sufficient to add only platform-independent signals.
from joker.
OK, I've removed OS-dependent signals for now and merged everything to master. Closing.
from joker.
Related Issues (20)
- joker.string/split of String Ignores Limit
- Tagged literals can cause read error even if hidden behind reader conditional HOT 1
- Valid Clojure Symbol/Keyword Names Rejected by Joker
- Joker Crashes Linting a ClojureScript Source File
- Joker Allows Shadowing Builtin Types HOT 1
- Recognize Mismatched Close Delimiters
- Support Arbitrary BigFloat Precision for stdlib Packages and "M"-Suffixed Constants HOT 2
- Piping standard input to starting subprocesses HOT 2
- Embedded Joker HOT 3
- Support (load "filename") HOT 4
- format overwrite HOT 1
- Exceptions from :parse-fn w/ joker.tools.cli are not caught HOT 2
- disable auto-complete in REPL HOT 2
- Parsing Expression Grammar HOT 1
- `pprint` to file HOT 2
- large-forked-stdout Fails with Go 1.19rc2
- Invalid use of / in symbol name HOT 2
- File locking? HOT 3
- Surrounding text with parens in the REPL HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from joker.