IRC channel logs

2021-09-11.log

back to list of logs

***chris is now known as Guest3024
<muradm>hi guile
<muradm>in my script i would like to follow output of some program, and depending on its output take some actions
<muradm>for now i do like (open-input-port ...), then in a (while ... loop calling (read-line ...)
<muradm>this looks messy, just wander if there is simplier way
<muradm>or should i just continue improving my mess? :)
<vijaymarupudi>Your approach sounds good to me
<muradm>hello guile
<muradm>in (ice-9 rdelim) should (read-line some-port) block if there is no input?
<muradm>not very clear from guile manual
<vijaymarupudi>It should block
<muradm>vijaymarupudi: cool.. also is it possible to get pid of some-port? where some-port is started with (open-input-pipe ...)
<muradm>i suppose (close-port some-port) won't kill the process, isn't it
<vijaymarupudi>muradm: I don't think so...
<RhodiumToad>it won't kill it but it will wait for it to end
<vijaymarupudi>I've had to resort to primitive-fork a decent amount in guile for many things
<RhodiumToad>I believe those are based on popen() and pclose(), which don't expose the pid
<vijaymarupudi>Looking at the implementation, it looks like it uses fork in C, and has the PID in scheme, but doesn't expose it
<muradm>you suggest to downgrade to (primitive-fork) in order to acqiure both pid and some how port
<vijaymarupudi>I guess that depends on the use case, what are you trying to do?
<muradm>i'm trying to 1) (open-input-pipe "inotifywait ...") to get ouput if file change notifications 2) while changes occur stop/start another process
<vijaymarupudi> I see, and why do you need to get the PID?
<muradm>if process on step 2 dies, restart it, if inotifywait dies, depending on the exit signal restart it or terminate loop and exit, also terminating the other process
<vijaymarupudi>Do you care about concurrency in checking those two things?
<vijaymarupudi>Otherwise you could just use an eof-object as an indicator that a process had died
<muradm>for waitpid on both inotifywait and second process
<muradm>eof-object does not give exit status
<vijaymarupudi>But then close-pipe does
<muradm>no, it gives #t if closed or #f if already classed
<muradm>clossed
<muradm>that is not process exit status
<muradm>looks like hard task to manage 2 processes... :)
<vijaymarupudi>I'm getting the exit code when I use it
<vijaymarupudi>I'm saying use close-pipe, not close-port
<muradm>hmm.. close-pipe.. i will try now. this will solve the inner second process issue problem
<muradm>but not outer inotifywait
<vijaymarupudi>Yes, if you care about concurrency, then primitive-fork in the only option I think
<vijaymarupudi>You might be able to use threads here, but I'm not well-versed in how processes and threads interact
<muradm> https://paste.rs/U3x
<muradm>this does not solve death of inotifywait
<muradm>but i will try now
<vijaymarupudi>I'm fairly certain threads can solve this, more easily than primitive-fork
<muradm>(close-pipe) blocks if process does not want to exit
<vijaymarupudi>Yep, but you should only call with when you get an eof indicator from read-line
<muradm>why?
<muradm>when eol, i close-pipe and break, when anything else, i close-pipe and open-output-pipe on next loop
<vijaymarupudi>Oh you want to kill it, then yeah, you can't do it without the
<vijaymarupudi>pid*
<muradm> https://github.com/ChaosEternal/guile-inotify2 this would be a bliss...
<vijaymarupudi>Is there a reason you're not using it?
<muradm>not packaged under guix.. :)
<muradm>also it's interface is somewhat weird
<muradm>looks like maps api almost one to one without adaptation to guile
<muradm>also old
<vijaymarupudi>Even if it works, I think you're going to face the same problem that you're facing now
<vijaymarupudi>You want to do two concurrent things at once
<vijaymarupudi>Although not having the PID makes it harder
<muradm>that would take a lot of code to write for such small problem :)
<muradm>probably a small helper library :D
<vijaymarupudi>fibers might help, but I've never used it
<vijaymarupudi>concurrency is a hard problem haha
<muradm>fibers won't help i think, from docs it says the same, when using fibers don't block, don't do syscalls etc.. :) they are more for parallel processing of tons of computations that do not block
<muradm>threads are the way to go for this task
<muradm>see fibers 3.1 Pitfals -> Blocking
<muradm>that is true for all environments i suppose..
<muradm>not specific to guile
<vijaymarupudi>I'm not so sure about that, they don't block as in wait while doing nothing, but in case they need to wait, they do other tasks in the event loop
<vijaymarupudi>I do agree that threads might be simpler
<muradm>(read-line) at least is blocking call
<vijaymarupudi>But not if you install suspendable-ports
<vijaymarupudi>I think*
<vijaymarupudi>See https://www.gnu.org/software/guile/docs/master/guile.html/Non_002dBlocking-I_002fO.html
<muradm>uh.. that will grow to high preformance implementation of task to manage 2 processes :D
<vijaymarupudi>Haha, well overengineering is always an option :)
<muradm> https://paste.rs/fQ8 some how this does not work..
<vijaymarupudi>When you use fork, you should be branching on the PID value
<muradm> https://paste.rs/guo
<vijaymarupudi>if it's zero, it's the child, if not, it's the parent
<muradm>damn.. https://paste.rs/EXp
<vijaymarupudi>You also have to setup the stdin and stdout of the new process properly using dup2 if you want to read from it.
<muradm>didn't get that from shepherd source
<muradm>yes, but i don't need now, stdout of inotifywait is of interest
<vijaymarupudi>Try looking at the output of this paste: https://paste.gnome.org/pubhrhlk3
<vijaymarupudi>Notice how it nevers get to the parent part
<muradm>literally sleep does not want to die https://paste.rs/i2X
<muradm>yes, yes.. i got that if zero? now :)
<muradm>thanks
<vijaymarupudi>I'm not sure what code you're running and what you are expecting
<muradm>(with-input-from-file ...) says that it will signal error if file does not exists, but i see that (with-input-from-file "/tmp/test" (match (read-line) ....)) where "/tmp/test does not exists, blocks on read-line call
<muradm>what does "error signaled" would mean..
<vijaymarupudi>Running that raised an error for me
<vijaymarupudi>Just an exception
<RhodiumToad>muradm: with-input-from-file expects a lambda as second arg
<RhodiumToad>(with-input-from-file "filename" (lambda () (match (read-line) ...)))
<RhodiumToad>i.e. it's not syntax
<muradm>oh... it said thunk
<RhodiumToad>a thunk is a procedure of arity 0
<muradm>yes.. thanks
<muradm>looks like (primitive-fork) child process inherits parents stdout/stderr
<vijaymarupudi>Yep, I would recommend reading the man page for fork()
<vijaymarupudi>I love the UNIX model of making processes
<muradm>this looks like doing thing https://paste.rs/NC1 :)
<muradm>setvbuf calls unnecessary there just removed
<muradm>but killing processes in such way leaves <defunct> processes
<muradm><defunct> solved with (sigaction SIGCHLD SIG_IGNore)
<RhodiumToad>the right way to deal with defunct processes is to properly wait for them
<muradm>yes, analysing this already https://paste.rs/ZgW
<muradm>now i think whole thing can be rewritten with signals... :)
<RhodiumToad>signals are much more of a problem than you might think
<muradm>why so?
<RhodiumToad>especially in an interpreted language like guile
<RhodiumToad>because you can do almost nothing safely in a signal handler
<RhodiumToad>the usual workaround for interpreters is to set some flag in the handler and then process it later, but that means that signal handling can be deferred in some cases arbitrarily far
<muradm>had to do this https://paste.rs/r3f
<muradm>when terminating parent process, children remain orphaned
<muradm>although, could not bind action for SIGKILL
<muradm>probably due to the fact of being last resort, no handlers are bindable
<muradm>also very interesting, sending first "kill pid" to guile has no effect, have to send another one
<muradm>then action getting triggered
<muradm>also that global state, not liking it very much
<RhodiumToad>SIGKILL can't be caught ever, it terminates the process unconditionally
<muradm>actually i think now that signals could be combined with fibers :)
<muradm>then there would not be blocking :)
<muradm>trully asynchronous :D