From a72245949a88b631c97e39fec70313f855e21ec2 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Mon, 22 Apr 2019 19:03:37 +0200 Subject: [PATCH] bug: suspendable put-bytevector. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit To reproduce, do something like ./pre-inst-env demos/websocket/8s-server.scm& chromium demos/websocket/ws-client.html or icecat demos/websocket/ws-client.html and reload browser window several times. The server should produce a backtrace like 18:59:44 janneke@dundal:~/src/8sync/bug [env] $ ./pre-inst-env demos/websocket/8s-server.scm ;;; note: source file /home/janneke/src/8sync/bug/demos/websocket/8s-server.scm ;;; newer than compiled /home/janneke/.cache/guile/ccache/2.2-LE-8-3.A/home/janneke/src/8sync/bug/demos/websocket/8s-server.scm.go ;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0 ;;; or pass the --no-auto-compile argument to disable. ;;; compiling /home/janneke/src/8sync/bug/demos/websocket/8s-server.scm ;;; compiled /home/janneke/.cache/guile/ccache/2.2-LE-8-3.A/home/janneke/src/8sync/bug/demos/websocket/8s-server.scm.go listening: 1236 Zzzzzzzz.... on-ws-connection: args=(#< 249ed80> 1) on-ws-message: args= (("/home/janneke/src/8sync/bug/demos/websocket/8s-server.scm")) on-message: ws: "Hello, Web Socket!" on-ws-message: args= (("/home/janneke/src/8sync/bug/demos/websocket/8s-server.scm")) on-message: ws: "Say: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA..." While reading request: In procedure fport_read: Connection reset by peer *** Caught exception with key 'system-error and arguments: ("fport_write" "~A" ("Broken pipe") (32)) *** In ice-9/boot-9.scm: 829:9 19 (catch #t # # …) 829:9 18 (catch #t # # …) 829:9 17 (catch #t # # …) 829:9 16 (catch #t # # …) 829:9 15 (catch #t # # …) In 8sync/actors.scm: 596:6 14 (call-catching-coroutine # _) 576:6 13 (call-catching-errors) In ice-9/boot-9.scm: 829:9 12 (catch #t # # …) In 8sync/actors.scm: 616:18 11 (_) In ice-9/boot-9.scm: 841:4 10 (with-throw-handler _ _ _) In 8sync/systems/web.scm: 167:10 9 (_ _ . _) In web/response.scm: 221:2 8 (write-response #< version: (1 . 0) code: 400 reason-phrase: #f headers: ((content-len…> …) In web/http.scm: 1199:2 7 (write-response-line (1 . 0) 400 "Bad Request" #) 1081:2 6 (write-http-version (1 . 0) #) In ice-9/suspendable-ports.scm: 662:12 5 (put-string # "HTTP/" _ _) 83:4 4 (write-bytes # #vu8(72 84 84 80 47 54 76 101 106 51 78 104 110 122 74 116 …) …) In unknown file: 3 (port-write # #vu8(72 84 84 80 47 54 76 101 106 51 78 104 110 122 74 116 …) …) In ice-9/boot-9.scm: 752:25 2 (dispatch-exception _ _ _) 751:25 1 (dispatch-exception 1 system-error ("fport_write" "~A" ("Broken pipe") (32))) In 8sync/agenda.scm: 597:23 0 (print-error-and-continue _ . _) *** Caught exception with key 'wrong-type-arg and arguments: ("port-write" "Wrong type argument in position ~A (expecting ~A): ~S" (1 "open output port" #) (#)) *** In ice-9/eval.scm: 619:8 19 (_ #(#(#))) In ice-9/boot-9.scm: 2312:4 18 (save-module-excursion _) 3822:12 17 (_) In 8sync/actors.scm: 812:6 16 (run-hive #< 28a6500> _ #:cleanup _ #:handle-signals _) In ice-9/control.scm: 91:24 15 (call-with-escape-continuation _) In 8sync/agenda.scm: 568:6 14 (run-agenda #< queue: (() . #f) prompt-tag: ("prompt") read-port-map: # …) 631:5 13 (agenda-run-once! #< queue: (() . #f) prompt-tag: ("prompt") read-port-map: #) In ice-9/boot-9.scm: 829:9 12 (catch #t # # …) 829:9 11 (catch #t # # …) 829:9 10 (catch #t # # …) 829:9 9 (catch #t # # …) In 8sync/actors.scm: 596:6 8 (call-catching-coroutine # _) 576:6 7 (call-catching-errors) In ice-9/boot-9.scm: 829:9 6 (catch #t # # …) In 8sync/actors.scm: 616:18 5 (_) In 8sync/systems/websocket/server.scm: 171:11 4 (websocket-server-send _ #< id: "f89a760cec1b14c9c6654de548156342:8" to: #(" …) In ice-9/suspendable-ports.scm: 83:5 3 (write-bytes # #vu8(83 97 121 58 32 65 65 65 65 65 65 65 65 65 65 65 65 # …) …) In unknown file: 2 (port-write #) In ice-9/boot-9.scm: 751:25 1 (dispatch-exception 0 wrong-type-arg ("port-write" "Wrong type argument in position ~A (expect…" …)) In 8sync/agenda.scm: 597:23 0 (print-error-and-continue _ . _) Zzzzzzzz.... C-c C-c The problem does not occur when enabling these lines (define put-bytevector (@ (ice-9 binary-ports) put-bytevector)) (module-define! (resolve-module '(8sync systems websocket frame)) 'put-bytevector put-bytevector) in demos/websocket/8s-server.scm * demos/websocket/ws-client.html: New file. * demos/websocket/8s-server.scm: New file. --- demos/websocket/8s-server.scm | 73 ++++++++++++++++++++++++++++++++++ demos/websocket/ws-client.html | 43 ++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100755 demos/websocket/8s-server.scm create mode 100644 demos/websocket/ws-client.html diff --git a/demos/websocket/8s-server.scm b/demos/websocket/8s-server.scm new file mode 100755 index 0000000..f271827 --- /dev/null +++ b/demos/websocket/8s-server.scm @@ -0,0 +1,73 @@ +#! /usr/bin/env guile +# -*-scheme-*- +!# + +;;; 8sync --- Asynchronous programming for Guile +;;; Copyright © 2019 Jan (janneke) Nieuwenhuizen +;;; +;;; This file is part of 8sync. +;;; +;;; 8sync is free software: you can redistribute it and/or modify it +;;; under the terms of the GNU Lesser General Public License as +;;; published by the Free Software Foundation, either version 3 of the +;;; License, or (at your option) any later version. +;;; +;;; 8sync is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU Lesser General Public License for more details. +;;; +;;; You should have received a copy of the GNU Lesser General Public +;;; License along with 8sync. If not, see . + +(define-module (8s-server) + #:use-module (oop goops) + #:use-module (8sync) + #:use-module (8sync systems web) + #:use-module (8sync systems websocket client) + #:use-module (8sync systems websocket server) + #:export (main)) + +(define %server-port 1236) + +(define-actor () + ((*init* sleeper-loop)) + (sleep-secs #:init-value 3 #:getter sleeper-sleep-secs)) + +(define (sleeper-loop actor message) + (while (actor-alive? actor) + (display "Zzzzzzzz....\n") + ;; Sleep for a bit + (8sleep (sleeper-sleep-secs actor)))) + +(define (main . args) + (let* ((hive (make-hive)) + (sleeper (bootstrap-actor hive )) + (suspendable-port-bug? #t) ;; server must send large message to browser + (server (bootstrap-actor + hive + #:port %server-port + #:on-ws-client-connect (lambda args + (format (current-error-port) "on-ws-client-connection: ~s\n" args)) + #:on-ws-client-disconnect (lambda args + (format (current-error-port) "on-ws-client-disconnect: ~s\n" args)) + #:on-ws-message (lambda (ws id msg) + (format (current-error-port) "on-message: ~s: ~s\n" 'ws + (if (< (string-length msg) 80) msg + (string-append (substring msg 0 77) "..."))) + (<- (actor-id ws) 'ws-send id msg) + (when suspendable-port-bug? + (<- (actor-id ws) 'ws-send id (string-append "Say: " (make-string (expt 2 16) #\A) "\n")))) + #:on-ws-open (lambda (ws) + (format (current-error-port) "on-open: ~s\n" ws))))) + (format (current-error-port) "listening: ~s\n" %server-port) + (run-hive hive '()))) + +;; HACK: Do not suspend writes to avoid +;; `The connection to ws://localhost:1236/ was interrupted while the page was loading.' (icecat) +;; `could not decode a text frame as utf-8' (ungoogled chromium) + +;; (define put-bytevector (@ (ice-9 binary-ports) put-bytevector)) +;; (module-define! (resolve-module '(8sync systems websocket frame)) 'put-bytevector put-bytevector) + +(main (command-line)) diff --git a/demos/websocket/ws-client.html b/demos/websocket/ws-client.html new file mode 100644 index 0000000..5e9c811 --- /dev/null +++ b/demos/websocket/ws-client.html @@ -0,0 +1,43 @@ + + + + + Ws test + + +

+ + + -- 2.31.1