From bf9fe659a93388e7f62320786160b74446768c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kr=C3=BCger?= <45282134+UweKrueger@users.noreply.github.com> Date: Fri, 9 Apr 2021 22:40:35 +0200 Subject: [PATCH] sync: fix `chan.close()` while a sending thread is waiting (#9654) --- vlib/sync/channel_close_test.v | 37 +++++++++++++++++++++++++++++++++- vlib/sync/channels.v | 3 +++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/vlib/sync/channel_close_test.v b/vlib/sync/channel_close_test.v index 07ce9a90eb..ba5070e2e4 100644 --- a/vlib/sync/channel_close_test.v +++ b/vlib/sync/channel_close_test.v @@ -1,4 +1,4 @@ -import sync +import time fn do_rec(ch chan int, resch chan i64) { mut sum := i64(0) @@ -71,3 +71,38 @@ fn test_channel_close_unbuffered() { sum += <-resch assert sum == i64(8000) * (8000 - 1) / 2 } + +fn test_channel_send_close_buffered() { + ch := chan int{cap: 1} + t := go fn (ch chan int) { + ch <- 31 + mut x := 45 + ch <- 17 or { + x = -133 + } + assert x == -133 + }(ch) + time.sleep(100 * time.millisecond) + ch.close() + mut r := <-ch + r = <-ch or { 23 } + assert r == 23 + t.wait() +} + +fn test_channel_send_close_unbuffered() { + time.sleep(1 * time.second) + ch := chan int{} + t := go fn (ch chan int) { + mut x := 31 + ch <- 177 or { + x = -71 + } + assert x == -71 + }(ch) + time.sleep(100 * time.millisecond) + ch.close() + r := <-ch or { 238 } + assert r == 238 + t.wait() +} diff --git a/vlib/sync/channels.v b/vlib/sync/channels.v index bae6526fcd..70b17491f0 100644 --- a/vlib/sync/channels.v +++ b/vlib/sync/channels.v @@ -165,6 +165,9 @@ pub fn (mut ch Channel) close() { } C.atomic_store_u16(&ch.write_sub_mtx, u16(0)) ch.writesem.post() + if ch.cap == 0 { + C.atomic_store_ptr(&ch.read_adr, voidptr(0)) + } ch.writesem_im.post() }