niko
2022-3-17 08:48:30

I ran the shell script on the webpage. The original version was whatever I got from apt


spdegabrielle
2022-3-17 13:12:59

oh great. Now I’m going to suspect everything I get from apt. I think I need to go back to getting software from the authors to be sure I have the current version. (to avoid bugs and known vulnerabilities)


laurent.orseau
2022-3-17 16:09:34

~…and of course I haven’t been able to reproduce the problem in an minimal example—and still can pinpoint the issue in my original code~ :confused:


sorawee
2022-3-17 16:15:21

Post to GitHub, maybe? (if your code can be shared publicly, that is)


laurent.orseau
2022-3-17 16:43:52

Aha, I do have a MWE (or MFE maybe): https://gist.github.com/Metaxal/def826defa710617a16ef5d6c3f5f7dc With (read in) it takes twice as long as with (with-input-from-string (read-line in) read) . Not sure exactly what’s happening. I think a single message is not enough for read alone.


laurent.orseau
2022-3-17 16:44:47

This is on Ubuntu 20.04LTS, Racket v8.4.0.3 [cs]


laurent.orseau
2022-3-17 16:46:33

This should work on Unix, as long as /usr/bin/env racket works, but not Windows.


sorawee
2022-3-17 16:48:27

FWIW, I got:

error writing to stream port system error: Broken pipe; errno=32 context...: /Users/sorawee/playground/server-worker.rkt:54:2 body of (submod "/Users/sorawee/playground/server-worker.rkt" worker) body of top-level when running the variant with read-line. It’s sporadic though. Not always happening. And I don’t know if the variant without read-line suffers the same problem.


laurent.orseau
2022-3-17 16:53:02

A broken pipe probably means that something broke the worker before that. Don’t you have another error message above?


sorawee
2022-3-17 16:54:59

nope


sorawee
2022-3-17 16:55:17

It appears to happen after the main script ends…


laurent.orseau
2022-3-17 16:58:41

oh, that’s fine. It’s just the cleaning up that’s rushed


laurent.orseau
2022-3-17 16:59:54

Probably the (sleep 2) is either skipped or not long enough for the workers to terminate, but we should actually kill them and close the ports instead


laurent.orseau
2022-3-17 18:41:04

The cleanup should be fixed now (I just killed the workers)


sorawee
2022-3-17 19:02:42

Here’s a version that uses thread instead of subprocess, and still has the behavior that you describe. Just trying to make it self-contained further.

#lang racket #\| Save this file to "server-worker.rkt" then run $ time racket server-worker.rkt Then toggle the commented expression in `read-msg` and again $ time racket server-worker.rkt Result: First run takes ~20s, while second run takes ~10s (as it should). \|# (struct worker (thd in out) #:property prop:evt (λ (self) (wrap-evt (worker-in self) (λ _ self))) #:transparent) (define (make-worker) (define-values (in-for-in out-for-in) (make-pipe)) (define-values (in-for-out out-for-out) (make-pipe)) (worker (thread (λ () (send-msg 'ready out-for-in) (let loop () (define cmd (do/debug (read-msg in-for-out))) (sleep 2) (send-msg (list 'done cmd) out-for-in) (loop)))) in-for-in out-for-out)) (define-syntax-rule (do/debug cmd) (let () (define-values (res cpu real gc) (time-apply (λ () cmd) '())) (eprintf "~a cpu: ~a real: ~a gc: ~a\n" (~a 'cmd #:min-width 50) cpu real gc) (apply values res))) (define (send-msg msg out) (writeln msg out) (flush-output out)) (define (read-msg in) ;; TOGGLE BETWEEN THESE TWO: (read in) #;(with-input-from-string (read-line in) read)) (module+ main (define workers (build-list 4 (λ _ (make-worker)))) (for ([t 20]) (printf "t: ~a\n" t) (define wk (begin #;do/debug (apply sync workers))) (begin #;do/debug (read-msg (worker-in wk))) (begin #;do/debug (send-msg (list 't t) (worker-out wk)))) (for-each (λ (w) (kill-thread (worker-thd w))) workers))



laurent.orseau
2022-3-17 19:08:01

So you do observe the issue too, it’s not just me?


sorawee
2022-3-17 19:08:43

yep


sorawee
2022-3-17 19:09:48

compared between read-line and read, the one with read-line are mostly 0s.

The one with read have a lot of 2000ms, with occasional 8000ms


sorawee
2022-3-17 19:09:53

And you sleep for 2s


sorawee
2022-3-17 19:10:50

read-line has 2s on the server side, on apply sync ....


laurent.orseau
2022-3-17 19:10:57

Yes indeed. i see 4000 and 6000 too


sorawee
2022-3-17 19:11:33

But read has significant multiple of 2s pretty much every command.


laurent.orseau
2022-3-17 19:12:32

I think one more write unblocks a previous read or something


laurent.orseau
2022-3-17 19:12:43

like buffer issues


laurent.orseau
2022-3-17 22:55:09

Does (open-output-nowhere) need to be closed? The docs don’t say


laurent.orseau
2022-3-17 23:01:54

More importantly, can something like with-limits with a timeout prevent with-output-to-file to close the output port when raising a resource exn? I’d expect not, but I’m getting the dreaded too many files opened error


greg
2022-3-17 23:11:48

As a starting point for any server that wants accept multiple “connections” (whether that’s TCP or some other protocol), I’d recommend following the examples in https://docs.racket-lang.org/more/index.html


greg
2022-3-17 23:12:28

And for instance there’s a good example of timing out something with a watcher thread, and freeing resources with a custodian, by the time you get to section 7 https://docs.racket-lang.org/more/index.html#%28part._.Terminating_.Connections%29