Last active
January 31, 2022 10:32
-
-
Save joetIO/ca0cfcf9dc87905d37a4fee7beb253c2 to your computer and use it in GitHub Desktop.
Checks if a Go channel is closed without touching/reading it (a very bad idea please do not use :) i was like 16 years old when i wrote this hacking go runtime, it's just a nice hack but def not memory safe lmao)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"unsafe" | |
"reflect" | |
) | |
func isChanClosed(ch interface{}) bool { | |
if reflect.TypeOf(ch).Kind() != reflect.Chan { | |
panic("only channels!") | |
} | |
// get interface value pointer, from cgo_export | |
// typedef struct { void *t; void *v; } GoInterface; | |
// then get channel real pointer | |
cptr := *(*uintptr)(unsafe.Pointer( | |
unsafe.Pointer(uintptr(unsafe.Pointer(&ch)) + unsafe.Sizeof(uint(0))), | |
)) | |
// this function will return true if chan.closed > 0 | |
// see hchan on https://github.com/golang/go/blob/master/src/runtime/chan.go | |
// type hchan struct { | |
// qcount uint // total data in the queue | |
// dataqsiz uint // size of the circular queue | |
// buf unsafe.Pointer // points to an array of dataqsiz elements | |
// elemsize uint16 | |
// closed uint32 | |
// ** | |
cptr += unsafe.Sizeof(uint(0))*2 | |
cptr += unsafe.Sizeof(unsafe.Pointer(uintptr(0))) | |
cptr += unsafe.Sizeof(uint16(0)) | |
return *(*uint32)(unsafe.Pointer(cptr)) > 0 | |
} | |
func main() { | |
ch := make(chan int64) | |
fmt.Println(isChanClosed(ch)) // -> false | |
close(ch) | |
fmt.Println(isChanClosed(ch)) // -> true | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment