v
v copied to clipboard
can read from a closed channel
Describe the bug
After a channel was closed, following read can read from the closed channel.
Reproduction Steps
cc.v
module main
fn main() {
ch := chan int{cap: 10}
mut received := []int{}
ch <- 1
ch.close() // close channel here
mut done := false
for !done {
select {
val := <-ch {
// should not be here
dump('received ch')
received << val
}
else {
// channel closed
dump('closed')
done = true
}
}
}
dump(received)
}
Expected Behavior
$ ./cc
[cc.v:19] 'closed': closed
[cc.v:25] received: []
Current Behavior
$ ./cc
[cc.v:14] 'received ch': received ch
^C
Possible Solution
No response
Additional Information/Context
No response
V version
V 0.4.10 566d22ab66b14655f1b1f2f4aa8396264ebf0c26
Environment details (OS name and version, etc.)
| V full version | V 0.4.10 566d22ab66b14655f1b1f2f4aa8396264ebf0c26 |
|---|---|
| OS | linux, Ubuntu 24.04.2 LTS |
| Processor | 8 cpus, 64bit, little endian, Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz |
| Memory | 7.54GB/15.51GB |
| V executable | /media/HD/github/kbkpbot/v/v |
| V last modified time | 2025-06-02 00:07:12 |
| V home dir | OK, value: /media/HD/github/kbkpbot/v |
| VMODULES | OK, value: /home/mars/.vmodules |
| VTMP | OK, value: /tmp/v_1000 |
| Current working dir | OK, value: /home/mars/v/bug/channel |
| Git version | git version 2.43.0 |
| V git status | weekly.2025.17-228-g8f1bf53f-dirty |
| .git/config present | true |
| cc version | cc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 |
| gcc version | gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 |
| clang version | Ubuntu clang version 18.1.3 (1ubuntu1) |
| tcc version | tcc version 0.9.28rc 2025-02-13 HEAD@f8bd136d (x86_64 Linux) |
| tcc git status | thirdparty-linux-amd64 696c1d84 |
| emcc version | N/A |
| glibc version | ldd (Ubuntu GLIBC 2.39-0ubuntu8.4) 2.39 |
[!NOTE] You can use the 👍 reaction to increase the issue's priority for developers.
Please note that only the 👍 reaction to the issue itself counts as a vote. Other reactions and those to comments will not be taken into account.
Connected to Huly®: V_0.6-23036
I don't know if is useful a channel in a single thread, but seems next complete select form mentioned in the docs, registers the whole history channel had:
fn main() {
ch := chan int{cap: 10}
mut received := []int{}
ch <- 1
ch <- 2
ch.close()
mut done := false
for !done {
if select {
val := <-ch {
received << val
println('received: ${received}')
}
} {
println('not closed yet')
} else {
println('closed')
done = true
}
}
}
received: [1]
not closed yet
received: [1, 2]
not closed yet
closed
close channel in another thread, also has this problem:
module main
fn main() {
ch := chan int{cap: 10}
block := chan bool{}
mut received := []int{}
spawn fn [block, ch] () {
ch <- 1
ch.close()
block <- true
}()
_ := <-block
mut done := false
for !done {
select {
val := <-ch {
// should not be here
dump('received ch')
received << val
}
else {
// channel closed
dump('channel closed')
done = true
}
}
}
dump(received)
}
$ ./ccc
[ccc.v:21] 'received ch': received ch
^C
how about go handle this?
In go this fails (with close or defaul is the same):
func main() {
c := make(chan int)
c <- 43
//close(c)
for {
select {
case i := <- c:
fmt.Println(i)
//default:
// println("?")
}
}
}
fatal error: all goroutines are asleep - deadlock!
You need more code to communicate:
func read(c chan int, s chan bool) {
i := <- c
fmt.Println(i)
s<- true
}
func write(c chan int) {
time.Sleep(1 * time.Second)
c <- 43
close(c)
}
func main() {
c := make(chan int)
s := make(chan bool)
go read(c, s)
go write(c)
<-s
}
43