mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-30 23:23:07 +00:00 
			
		
		
		
	Work on bug #1556
This commit is contained in:
		| @@ -3877,8 +3877,8 @@ | |||||||
| (compwhen (dyn 'net/listen) | (compwhen (dyn 'net/listen) | ||||||
|   (defn net/server |   (defn net/server | ||||||
|     "Start a server asynchronously with `net/listen` and `net/accept-loop`. Returns the new server stream." |     "Start a server asynchronously with `net/listen` and `net/accept-loop`. Returns the new server stream." | ||||||
|     [host port &opt handler type] |     [host port &opt handler type no-reuse] | ||||||
|     (def s (net/listen host port type)) |     (def s (net/listen host port type no-reuse)) | ||||||
|     (if handler |     (if handler | ||||||
|       (ev/go (fn [] (net/accept-loop s handler)))) |       (ev/go (fn [] (net/accept-loop s handler)))) | ||||||
|     s)) |     s)) | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
| * Copyright (c) 2024 Calvin Rose | * Copyright (c) 2025 Calvin Rose | ||||||
| * | * | ||||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
| * of this software and associated documentation files (the "Software"), to | * of this software and associated documentation files (the "Software"), to | ||||||
| @@ -1789,6 +1789,22 @@ void janet_stream_edge_triggered(JanetStream *stream) { | |||||||
| } | } | ||||||
|  |  | ||||||
| void janet_stream_level_triggered(JanetStream *stream) { | void janet_stream_level_triggered(JanetStream *stream) { | ||||||
|  |     /* On macos, we seem to need to delete any registered events before re-registering without | ||||||
|  |      * EV_CLEAR, otherwise the new event will still have EV_CLEAR set erroneously. This could be a | ||||||
|  |      * kernel bug, but unfortunately the specification is vague here, esp. in regards to where and when | ||||||
|  |      * EV_CLEAR is set automatically. */ | ||||||
|  |     struct kevent kevs[2]; | ||||||
|  |     int length = 0; | ||||||
|  |     if (stream->flags & (JANET_STREAM_READABLE | JANET_STREAM_ACCEPTABLE)) { | ||||||
|  |         EV_SETx(&kevs[length++], stream->handle, EVFILT_READ, EV_DELETE, 0, 0, stream); | ||||||
|  |     } | ||||||
|  |     if (stream->flags & JANET_STREAM_WRITABLE) { | ||||||
|  |         EV_SETx(&kevs[length++], stream->handle, EVFILT_WRITE, EV_DELETE, 0, 0, stream); | ||||||
|  |     } | ||||||
|  |     int status; | ||||||
|  |     do { | ||||||
|  |         status = kevent(janet_vm.kq, kevs, length, NULL, 0, NULL); | ||||||
|  |     } while (status == -1 && errno == EINTR); | ||||||
|     janet_register_stream_impl(stream, 0); |     janet_register_stream_impl(stream, 0); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -554,7 +554,10 @@ JANET_CORE_FN(cfun_net_connect, | |||||||
|     int err = WSAGetLastError(); |     int err = WSAGetLastError(); | ||||||
|     freeaddrinfo(ai); |     freeaddrinfo(ai); | ||||||
| #else | #else | ||||||
|     int status = connect(sock, addr, addrlen); |     int status; | ||||||
|  |     do { | ||||||
|  |         status = connect(sock, addr, addrlen); | ||||||
|  |     } while (status == -1 && errno == EINTR); | ||||||
|     int err = errno; |     int err = errno; | ||||||
|     if (is_unix) { |     if (is_unix) { | ||||||
|         janet_free(ai); |         janet_free(ai); | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| # Copyright (c) 2023 Calvin Rose & contributors | # Copyright (c) 2025 Calvin Rose & contributors | ||||||
| # | # | ||||||
| # Permission is hereby granted, free of charge, to any person obtaining a copy | # Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
| # of this software and associated documentation files (the "Software"), to | # of this software and associated documentation files (the "Software"), to | ||||||
| @@ -199,7 +199,7 @@ | |||||||
|   (assert s "made server 1") |   (assert s "made server 1") | ||||||
|  |  | ||||||
|   (defn test-echo [msg] |   (defn test-echo [msg] | ||||||
|     (with [conn (net/connect test-host test-port)] |     (with [conn (assert (net/connect test-host test-port))] | ||||||
|       (net/write conn msg) |       (net/write conn msg) | ||||||
|       (def res (net/read conn 1024)) |       (def res (net/read conn 1024)) | ||||||
|       (assert (= (string res) msg) (string "echo " msg)))) |       (assert (= (string res) msg) (string "echo " msg)))) | ||||||
| @@ -213,6 +213,7 @@ | |||||||
|  |  | ||||||
| # Test on both server and client | # Test on both server and client | ||||||
| # 504411e | # 504411e | ||||||
|  | (var iterations 0) | ||||||
| (defn names-handler | (defn names-handler | ||||||
|   [stream] |   [stream] | ||||||
|   (defer (:close stream) |   (defer (:close stream) | ||||||
| @@ -220,21 +221,26 @@ | |||||||
|     (ev/read stream 1) |     (ev/read stream 1) | ||||||
|     (def [host port] (net/localname stream)) |     (def [host port] (net/localname stream)) | ||||||
|     (assert (= host test-host) "localname host server") |     (assert (= host test-host) "localname host server") | ||||||
|     (assert (= port (scan-number test-port)) "localname port server"))) |     (assert (= port (scan-number test-port)) "localname port server") | ||||||
|  |     (++ iterations) | ||||||
|  |     (ev/write stream " "))) | ||||||
|  |  | ||||||
| # Test localname and peername | # Test localname and peername | ||||||
| # 077bf5eba | # 077bf5eba | ||||||
| (repeat 10 | (repeat 10 | ||||||
|   (with [s (net/server test-host test-port names-handler)] |   (with [s (net/server test-host test-port names-handler)] | ||||||
|     (repeat 10 |     (repeat 10 | ||||||
|       (with [conn (net/connect test-host test-port)] |       (with [conn (assert (net/connect test-host test-port))] | ||||||
|         (def [host port] (net/peername conn)) |         (def [host port] (net/peername conn)) | ||||||
|         (assert (= host test-host) "peername host client ") |         (assert (= host test-host) "peername host client ") | ||||||
|         (assert (= port (scan-number test-port)) "peername port client") |         (assert (= port (scan-number test-port)) "peername port client") | ||||||
|         # let server close |         (++ iterations) | ||||||
|         (ev/write conn " ")))) |         (ev/write conn " ") | ||||||
|  |         (ev/read conn 1)))) | ||||||
|   (gccollect)) |   (gccollect)) | ||||||
|  |  | ||||||
|  | (assert (= iterations 200) "localname and peername not enough checks") | ||||||
|  |  | ||||||
| # Create pipe | # Create pipe | ||||||
| # 12f09ad2d | # 12f09ad2d | ||||||
| (var pipe-counter 0) | (var pipe-counter 0) | ||||||
| @@ -422,7 +428,7 @@ | |||||||
|   (assert (= result text) (string/format "expected %v, got %v" text result))) |   (assert (= result text) (string/format "expected %v, got %v" text result))) | ||||||
|  |  | ||||||
| # Now do our telnet chat | # Now do our telnet chat | ||||||
| (def bob (net/connect test-host test-port :stream)) | (def bob (assert (net/connect test-host test-port :stream))) | ||||||
| (expect-read bob "Whats your name?\n") | (expect-read bob "Whats your name?\n") | ||||||
| (if (= :mingw (os/which)) | (if (= :mingw (os/which)) | ||||||
|   (net/write bob "bob") |   (net/write bob "bob") | ||||||
| @@ -432,7 +438,7 @@ | |||||||
|     (file/flush fbob) |     (file/flush fbob) | ||||||
|     (:close fbob))) |     (:close fbob))) | ||||||
| (expect-read bob "Welcome bob\n") | (expect-read bob "Welcome bob\n") | ||||||
| (def alice (net/connect test-host test-port)) | (def alice (assert (net/connect test-host test-port))) | ||||||
| (expect-read alice "Whats your name?\n") | (expect-read alice "Whats your name?\n") | ||||||
| (net/write alice "alice") | (net/write alice "alice") | ||||||
| (expect-read alice "Welcome alice\n") | (expect-read alice "Welcome alice\n") | ||||||
| @@ -446,7 +452,7 @@ | |||||||
| (expect-read bob "[alice]:hi\n") | (expect-read bob "[alice]:hi\n") | ||||||
|  |  | ||||||
| # Ted joins the chat server | # Ted joins the chat server | ||||||
| (def ted (net/connect test-host test-port)) | (def ted (assert (net/connect test-host test-port))) | ||||||
| (expect-read ted "Whats your name?\n") | (expect-read ted "Whats your name?\n") | ||||||
| (net/write ted "ted") | (net/write ted "ted") | ||||||
| (expect-read ted "Welcome ted\n") | (expect-read ted "Welcome ted\n") | ||||||
| @@ -485,9 +491,31 @@ | |||||||
| (ev/chan-close c) | (ev/chan-close c) | ||||||
|  |  | ||||||
| # soreuseport on unix domain sockets | # soreuseport on unix domain sockets | ||||||
| (compwhen (= :linux (os/which)) | (compwhen (or (= :macos (os/which)) (= :linux (os/which))) | ||||||
|   (assert-no-error "unix-domain socket reuseaddr" |   (assert-no-error "unix-domain socket reuseaddr" | ||||||
|                    (let [s (net/listen :unix "./unix-domain-socket" :stream)] |                    (let [s (net/listen :unix "./unix-domain-socket" :stream)] | ||||||
|                      (:close s)))) |                      (:close s)))) | ||||||
|  |  | ||||||
|  | # net/accept-loop level triggering | ||||||
|  | (gccollect) | ||||||
|  | (def maxconn 50) | ||||||
|  | (var connect-count 0) | ||||||
|  | (defn level-trigger-handling | ||||||
|  |   [conn &] | ||||||
|  |   (with [conn conn] | ||||||
|  |     (ev/write conn (ev/read conn 4096)) | ||||||
|  |     (++ connect-count))) | ||||||
|  | (def s (assert (net/server test-host test-port level-trigger-handling))) | ||||||
|  | (def cons @[]) | ||||||
|  | (repeat maxconn (array/push cons (assert (net/connect test-host test-port)))) | ||||||
|  | (assert (= maxconn (length cons))) | ||||||
|  | (defn do-connect [i] | ||||||
|  |   (with [c (get cons i)] | ||||||
|  |     (ev/write c "abc123") | ||||||
|  |     (ev/read c 4096))) | ||||||
|  | (for i 0 maxconn (ev/spawn (do-connect i))) | ||||||
|  | (ev/sleep 0.1) | ||||||
|  | (assert (= maxconn connect-count)) | ||||||
|  | (:close s) | ||||||
|  |  | ||||||
| (end-suite) | (end-suite) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose