Skip to content

Commit 89c391f

Browse files
authored
Merge 050fc94 into d087834
2 parents d087834 + 050fc94 commit 89c391f

File tree

5 files changed

+63
-10
lines changed

5 files changed

+63
-10
lines changed

src/internal/event_loop/poll.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ int moonbitlang_async_poll_register(
5252
events |= EPOLLONESHOT;
5353

5454
events |= EPOLLET;
55+
events |= EPOLLRDHUP;
5556

5657
epoll_data_t data;
5758
data.u64 = fd;

src/tls/bio.mbt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ fn Endpoint::try_write(ep : Endpoint, src : C_Buffer, len : Int) -> Int {
213213
async fn Endpoint::wait(ep : Endpoint) -> Unit raise {
214214
match ep.state {
215215
Error(err) => raise err
216-
Closed | Idle | Blocked => ()
216+
Closed => return
217+
Idle | Blocked => ()
217218
}
218219
let coro = @coroutine.current_coroutine()
219220
ep.waiters.add(coro)

src/tls/moon.pkg.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
],
77
"test-import": [
88
"moonbitlang/async",
9-
"moonbitlang/async/pipe"
9+
"moonbitlang/async/pipe",
10+
"moonbitlang/async/socket"
1011
],
1112
"native-stub": [ "stub.c" ]
1213
}

src/tls/shutdown_test.mbt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2025 International Digital Economy Academy
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
///|
16+
test "peer close connection" {
17+
let port = 4208
18+
@async.with_event_loop(fn(root) {
19+
// server
20+
root.spawn_bg(fn() {
21+
let server = @socket.TCPServer::new(
22+
@socket.Addr::parse("127.0.0.1:\{port}"),
23+
)
24+
defer server.close()
25+
let (conn, _) = server.accept()
26+
defer conn.close()
27+
let server = @tls.TLS::server(
28+
conn,
29+
private_key_file="test_keys/key.pem",
30+
private_key_type=PEM,
31+
certificate_file="test_keys/cert.pem",
32+
certificate_type=PEM,
33+
)
34+
defer server.close()
35+
@async.sleep(100)
36+
// the server already closed the connection
37+
server.shutdown()
38+
})
39+
// client
40+
root.spawn_bg(fn() {
41+
let conn = @socket.TCP::connect(@socket.Addr::parse("127.0.0.1:\{port}"))
42+
defer conn.close()
43+
let client = @tls.TLS::client(conn, verify=false)
44+
defer client.close()
45+
@async.sleep(50)
46+
// close the underlying connection directly
47+
})
48+
})
49+
}

src/tls/tls.mbt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -250,15 +250,16 @@ pub fn TLS::close(self : TLS) -> Unit {
250250
/// to prevent the program from haning indefinitely.
251251
pub async fn TLS::shutdown(self : TLS) -> Unit raise {
252252
while self.ssl.shutdown() is ret && ret <= 0 {
253-
if ret == 0 {
254-
self.read_end.wait()
253+
let err = if ret == 0 {
254+
SSL_ERROR_WANT_READ
255255
} else {
256-
let err = self.ssl.get_error(ret)
257-
if err is SSL_ERROR_ZERO_RETURN {
258-
// do not raise error on non-compilant peer
259-
break
260-
}
261-
self.handle_error(err)
256+
self.ssl.get_error(ret)
257+
}
258+
self.handle_error(err)
259+
match err {
260+
SSL_ERROR_WANT_READ if self.read_end.state is Closed => break
261+
SSL_ERROR_WANT_WRITE if self.write_end.state is Closed => break
262+
_ => ()
262263
}
263264
}
264265
}

0 commit comments

Comments
 (0)