[go-nuts] Re: //go:norace doesn't effect ABI0 wrapper

2022-11-30 Thread Cuong Manh Le


See my suggestion here: 
https://github.com/ebitengine/purego/issues/71#issuecomment-1332545306

For //go:norace and ABI wrapper functions, there's no instrument emitted. 
Your problem is that the compiler know there's a native ABI0 implementation 
for x_cgo_init, so calling it from assembly is force to use the ABI0 one, 
not the ABI wrapper.

On Wednesday, November 30, 2022 at 11:30:38 PM UTC+7 Jarrett Kuklis wrote:

> I am one of the main contributors to ebitengine/purego 
>  a library that aims to call into C 
> code without invoking the C compiler. The main platform of support is 
> darwin on arm64 and amd64. It uses //cgo_import_dynamic comments to get the 
> symbols and calls them using runtime.cgocall.
>
> That runtime function requires that runtime/cgo be imported which requires 
> C. I used the work of notti/nocgo  as 
> inspiration to write an implementation of runtime/cgo entirely in Go 
> (located at internal/fakecgo 
> ). It 
> has worked for the ebitengine  
> project really well. 
>
> However, I was looking at the draft Go 1.20 release notes and saw that 
> -race no longer requires Cgo to work on macOS. Which I am all for and 
> really excited about! This means though that when -race and CGO_ENABLED=0 
> our faked runtime/cgo package has race code placed in it. From what I can 
> tell this is bad because the code in this package is faking being C so it 
> shouldn't call into the race detector. And it will SIGSEGV jumping to any 
> code that tries to call it since the runtime isn't fully initialized by the 
> time these functions are called.
>
> There is an issue here  that 
> has more information about the issue.
>
> Obviously, I tried using //go:norace which indeed does remove the race 
> code from the function but the ABI0 wrapper still has the race detector 
> code. The functions are called from assembly since we need to move from the 
> C ABI to Go ABI which forces us into calling the ABI0 wrapper. I can't use 
>  since that is only allowed in the runtime. As far as I can 
> tell there is no way around the wrapper.
>
> So I was wondering if this is a bug? Shouldn't the //go:norace comment 
> also apply the the ABI wrappers? If not, is there any other suggestions as 
> to how purego could keep functioning when CGO_ENABLED=0 and -race are 
> defined?
>
> I've had a hard time debugging this since no debugger I've tested links to 
> the program before it crashes with SIGSEGV. And there is no stack trace. I 
> may be missing something so I am eager to learn!
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/fd190e4f-8054-497c-820d-3d0de60cd768n%40googlegroups.com.


[go-nuts] Re: Question on 'src/internal/singleflight': The return result of the ForgetUnshared method seems to be inaccurate

2022-09-22 Thread Cuong Manh Le
I sent https://go-review.googlesource.com/c/go/+/433315 for fixing the 
issue.

On Friday, September 23, 2022 at 10:59:03 AM UTC+7 atomic wrote:

> No wonder I didn't find related questions, the method names in the two 
> packages are different:
> One is Forget and the other is ForgetUnshared
>
> 在2022年9月23日星期五 UTC+8 11:05:51 写道:
>
>> Seems to me this commit is not port to the internal singleflight: 
>> https://github.com/golang/sync/commit/56d357773e8497dfd526f0727e187720d1093757
>>
>> On Friday, September 23, 2022 at 9:23:29 AM UTC+7 atomic wrote:
>>
>>> Thank you so much, so happy, you are amazing.
>>> You answered a question that has been bothering me for days, I opened an 
>>> issue on github, can you submit a pr to fix this?
>>> https://github.com/golang/go/issues/55343
>>>
>>> 在2022年9月23日星期五 UTC+8 06:23:13 写道:
>>>
 And here's a proof-of-concept fix which seems to do the job:

 --- main.go.orig2022-09-21 13:14:10.0 +0100
 +++ main.go2022-09-22 23:19:54.0 +0100
 @@ -27,6 +27,7 @@
  // not written after the WaitGroup is done.
  dups  int
  chans []chan<- Result
 +forgotten bool
  }

  // Group represents a class of work and forms a namespace in
 @@ -101,7 +102,9 @@
  c.wg.Done()

  g.mu.Lock()
 -delete(g.m, key)
 +if !c.forgotten {
 +delete(g.m, key)
 +}
  for _, ch := range c.chans {
  ch <- Result{c.val, c.err, c.dups > 0}
  }
 @@ -121,6 +124,7 @@
  return true
  }
  if c.dups == 0 {
 +c.forgotten = true
  delete(g.m, key)
  return true
  }

 On Thursday, 22 September 2022 at 23:16:22 UTC+1 Brian Candler wrote:

> OK, I think I have it.  It's ugly.
>
> Firstly, note that multiple instances of doCall can be running for the 
> same key.  This happens when:
>
> 1. you invoke DoChan.  This inserts a 'c' (call struct) into the map 
> and starts doCall in a goroutine.
> 2. at this point it's not shared: i.e. you don't call DoChan again 
> with the same key (yet).
> 3. you invoke ForgetUnshared on this key. This "detaches" it, but 
> doCall carries on running. It has its own local copy of 'c' so it knows 
> where to send the result, even though the map is now empty.
> 4. you invoke DoChan again with the same key.  This inserts a new 'c' 
> into the map and starts a new doCall goroutine.
>
> At this point, you have two instances of doCall running, and the map 
> is pointing at the second one.
>
> This is where it gets ugly.
>
> 5. you invoke DoChan yet again with the same key. This turns it into a 
> shared task, with c.dups > 0, len(c.chans) > 1.
> 6. the first instance of doCall terminates.  At this point it 
> unconditionally removes the key from the map - even though it had 
> previously been removed by ForgetUnshared!
>
> func (g *Group) doCall(c *call, key string, fn func() (interface{}, 
> error)) {
> c.val, c.err = fn()
> c.wg.Done()
>
> g.mu.Lock()
> *delete(g.m, key)//  NOTE*
> for _, ch := range c.chans {
> ch <- Result{c.val, c.err, c.dups > 0}
> }
> g.mu.Unlock()
> }
>
> So, even though it's the first instance of doCall which is 
> terminating, it's removing the second instance of doCall from the map.  
> This is now also a detached task.
>
> 7. In one of the two goroutines, the timeout event occurs.  It calls 
> ForgetUnshared, which happily returns true because the key does not exist 
> in the map - and therefore you proceed to cancel the context.
>
> But actually a task with this key *is* running; and furthermore, it is 
> a shared task, with 2 channel receivers.
>
> 8. Once the sleep has completed in the task function, it notices that 
> the context is cancelled and returns an error.
>
> 9. doCall sends the resulting error down multiple channels (those you 
> started in steps 4 and 5 above)
>
> 10. The select { case res := <-ch } triggers in the *other* goroutine 
> - the one which didn't have a timeout. Hence it receives the error, and 
> that's where you panic().
>
> On Thursday, 22 September 2022 at 20:37:07 UTC+1 Brian Candler wrote:
>
>> OK, I see where you're coming from - and I agree, this is a difficult 
>> one!
>>
>> The point you were making is that
>>
>> if g.ForgetUnshared(key) {
>> cancel()
>> }
>>
>> should only invoke cancel() if this result wasn't shared: i.e. 
>> there's only one receiver in the c.chans array, and c.dups == 0.  So 
>> where's 

[go-nuts] Re: Question on 'src/internal/singleflight': The return result of the ForgetUnshared method seems to be inaccurate

2022-09-22 Thread Cuong Manh Le
Seems to me this commit is not port to the internal 
singleflight: 
https://github.com/golang/sync/commit/56d357773e8497dfd526f0727e187720d1093757

On Friday, September 23, 2022 at 9:23:29 AM UTC+7 atomic wrote:

> Thank you so much, so happy, you are amazing.
> You answered a question that has been bothering me for days, I opened an 
> issue on github, can you submit a pr to fix this?
> https://github.com/golang/go/issues/55343
>
> 在2022年9月23日星期五 UTC+8 06:23:13 写道:
>
>> And here's a proof-of-concept fix which seems to do the job:
>>
>> --- main.go.orig2022-09-21 13:14:10.0 +0100
>> +++ main.go2022-09-22 23:19:54.0 +0100
>> @@ -27,6 +27,7 @@
>>  // not written after the WaitGroup is done.
>>  dups  int
>>  chans []chan<- Result
>> +forgotten bool
>>  }
>>
>>  // Group represents a class of work and forms a namespace in
>> @@ -101,7 +102,9 @@
>>  c.wg.Done()
>>
>>  g.mu.Lock()
>> -delete(g.m, key)
>> +if !c.forgotten {
>> +delete(g.m, key)
>> +}
>>  for _, ch := range c.chans {
>>  ch <- Result{c.val, c.err, c.dups > 0}
>>  }
>> @@ -121,6 +124,7 @@
>>  return true
>>  }
>>  if c.dups == 0 {
>> +c.forgotten = true
>>  delete(g.m, key)
>>  return true
>>  }
>>
>> On Thursday, 22 September 2022 at 23:16:22 UTC+1 Brian Candler wrote:
>>
>>> OK, I think I have it.  It's ugly.
>>>
>>> Firstly, note that multiple instances of doCall can be running for the 
>>> same key.  This happens when:
>>>
>>> 1. you invoke DoChan.  This inserts a 'c' (call struct) into the map and 
>>> starts doCall in a goroutine.
>>> 2. at this point it's not shared: i.e. you don't call DoChan again with 
>>> the same key (yet).
>>> 3. you invoke ForgetUnshared on this key. This "detaches" it, but doCall 
>>> carries on running. It has its own local copy of 'c' so it knows where to 
>>> send the result, even though the map is now empty.
>>> 4. you invoke DoChan again with the same key.  This inserts a new 'c' 
>>> into the map and starts a new doCall goroutine.
>>>
>>> At this point, you have two instances of doCall running, and the map is 
>>> pointing at the second one.
>>>
>>> This is where it gets ugly.
>>>
>>> 5. you invoke DoChan yet again with the same key. This turns it into a 
>>> shared task, with c.dups > 0, len(c.chans) > 1.
>>> 6. the first instance of doCall terminates.  At this point it 
>>> unconditionally removes the key from the map - even though it had 
>>> previously been removed by ForgetUnshared!
>>>
>>> func (g *Group) doCall(c *call, key string, fn func() (interface{}, 
>>> error)) {
>>> c.val, c.err = fn()
>>> c.wg.Done()
>>>
>>> g.mu.Lock()
>>> *delete(g.m, key)//  NOTE*
>>> for _, ch := range c.chans {
>>> ch <- Result{c.val, c.err, c.dups > 0}
>>> }
>>> g.mu.Unlock()
>>> }
>>>
>>> So, even though it's the first instance of doCall which is terminating, 
>>> it's removing the second instance of doCall from the map.  This is now also 
>>> a detached task.
>>>
>>> 7. In one of the two goroutines, the timeout event occurs.  It calls 
>>> ForgetUnshared, which happily returns true because the key does not exist 
>>> in the map - and therefore you proceed to cancel the context.
>>>
>>> But actually a task with this key *is* running; and furthermore, it is a 
>>> shared task, with 2 channel receivers.
>>>
>>> 8. Once the sleep has completed in the task function, it notices that 
>>> the context is cancelled and returns an error.
>>>
>>> 9. doCall sends the resulting error down multiple channels (those you 
>>> started in steps 4 and 5 above)
>>>
>>> 10. The select { case res := <-ch } triggers in the *other* goroutine - 
>>> the one which didn't have a timeout. Hence it receives the error, and 
>>> that's where you panic().
>>>
>>> On Thursday, 22 September 2022 at 20:37:07 UTC+1 Brian Candler wrote:
>>>
 OK, I see where you're coming from - and I agree, this is a difficult 
 one!

 The point you were making is that

 if g.ForgetUnshared(key) {
 cancel()
 }

 should only invoke cancel() if this result wasn't shared: i.e. there's 
 only one receiver in the c.chans array, and c.dups == 0.  So where's the 
 race, given that everything in g is done under a mutex?

 What I have discovered so far is: when g.ForgetUnshared(key) returns 
 true and the problem occurs, the key is not present in the map (as opposed 
 to being present with c.dups == 0).  But I've not been able to work out 
 why 
 yet.

 Incidentally, a minor style observation: you passed in ctx to your go 
 func(...), but not cancel. As far as I can see, both ctx and cancel are 
 local variables which drop immediately out of scope - there's no way they 
 can be 

[go-nuts] Re: Question on 'src/internal/singleflight': The return result of the ForgetUnshared method seems to be inaccurate

2022-09-21 Thread Cuong Manh Le
Hello,

You use time.Sleep in your program, so the behavior is not predictable. In 
fact, I get it success or panic randomly.

You can see https://go-review.googlesource.com/c/sync/+/424114 to see a 
predictable test of ForgetUnshared .

On Wednesday, September 21, 2022 at 1:45:24 PM UTC+7 atomic wrote:

> hello
>
> I find that the `src/internal/singleflight/singleflight.go 
> ForgetUnshared()` method returns results that are not always expected
>
> For this I wrote a test code, I copied the code in the 
> src/internal/singleflight/singleflight.go file to the main package, and 
> wrote a main function to test it, if ForgetUnshared() returns correctly, 
> this code It should not panic, but the fact that it will panic every time 
> it runs, is there something wrong with my understanding of ForgetUnshared()?
>
> The test code cannot be run in goplay, so I posted a link: 
> https://gist.github.com/dchaofei/e07547bce17d94c3e05b1b2a7230f62f
>
> The go version I use for testing is 1.16, 1.19.1
>
> result:
> ```
> $ go run cmd/main.go
> panic: callUUID=[9314284969 <(931)%20428-4969>] err=[context canceled] 
> currentUUId=[6980556786]
> ```
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/a528d3d5-d163-4626-a0a4-a33640392dedn%40googlegroups.com.


Re: [go-nuts] Re: go1.17rc2 fails to compile slice-to-array-pointer conversions if go.mod doesn't specify go directive

2021-08-11 Thread Cuong Manh Le
> go run -gcflags="-lang=go1.17" main.go
>
> doesn't work either.

Because what was run:

```
/Users/cuonglm/sdk/gotip/pkg/tool/darwin_arm64/compile -o
$WORK/b001/_pkg_.a -trimpath "$WORK/b001=>" -shared -lang=go1.17 -p main
-lang=go1.16 -complete -buildid iarBRwadYSTC65zcr7pK/iarBRwadYSTC65zcr7pK
-dwarf=false -D _/Users/cuonglm/t -importcfg $WORK/b001/importcfg -pack
./main.go $WORK/b001/_gomod_.go
```

Notice "-lang" is passed two times, and the later "-lang=go1.16" wins.

Cuong Manh Le
https://cuonglm.xyz


On Thu, Aug 12, 2021 at 7:56 AM tapi...@gmail.com 
wrote:

> BTW,
>
> go run -gcflags="-lang=go1.17" main.go
>
> doesn't work either.
>
> On Wednesday, August 11, 2021 at 10:45:05 AM UTC-4 tapi...@gmail.com
> wrote:
>
>> // main.go
>> package main
>>
>> func main() {
>> var s = []int{1, 2, 3}
>> var pa = (*[2]int)(s[1:])
>> println(pa[1])
>> }
>>
>> $ go run main.go
>> # command-line-arguments
>> ./main.go:6:23: cannot convert s[1:] (type []int) to type *[2]int:
>> conversion of slices to array pointers only supported as of
>> -lang=go1.17
>>
>> Is it the deliberate design? Shouldn't the lang value be the highest
>> language version supported by the current used toolchain?
>>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/06c2c090-d73d-4642-9b16-493e716222c4n%40googlegroups.com
> <https://groups.google.com/d/msgid/golang-nuts/06c2c090-d73d-4642-9b16-493e716222c4n%40googlegroups.com?utm_medium=email_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CALS7p_dgwuZ%3DNcjf0HcX0SiFt_%2BwMAW3aUsN%3D6r2XYpzRqGDow%40mail.gmail.com.


Re: [go-nuts] On tip, arguments of panic escape to heap

2021-05-23 Thread Cuong Manh Le
Hi,

It's normal, go1.16 and before is just incorrect for not reporting that
escaping. See: https://go-review.googlesource.com/c/go/+/284412

Cheers,
Cuong

On Sun, May 23, 2021 at 2:43 PM tapi...@gmail.com 
wrote:

> Go 1.16 doesn't make this.
> Is it nornal?
>
> package main
>
> func main(){
> panic("abc") // "abc" escapes to heap
> }
>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/936dcc57-c507-402e-9811-4216c5d0f694n%40googlegroups.com
> 
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CALS7p_cQX1p%2BC-SBD%3DGqq9Rpu1bqe%3DLCzS_JZPw11%3D5DLE%2BJOg%40mail.gmail.com.


Re: [go-nuts] Is unsafe.Pointer(reflect.Value.UnsafeAddr()) safe?

2021-04-18 Thread Cuong Manh Le
What's your platform?

On M1, checkptr reports an error for me. The code:

ptr := unsafe.Pointer(rf.UnsafeAddr())


is safe, but:

x := rf.UnsafeAddr()
ptr = unsafe.Pointer(x)


is not.

Cuong Manh Le
https://cuonglm.xyz


On Sun, Apr 18, 2021 at 6:46 AM Name No  wrote:

>
> reflect.Value.UnsafeAddr has the commence attached like that:
>
> //go:nocheckptr
> // This prevents inlining Value.UnsafeAddr when -d=checkptr is enabled,
> // which ensures cmd/compile can recognize unsafe.Pointer(v.UnsafeAddr())
> // and make an exception.
>
> Seems it is saying unsafe.Pointer(reflect.Value.UnsafeAddr())  is
> dangerous that go:nocheckptr can disable UnsafeAddr  from inline, so
> cmd/compile can detect it is a function call and raise an exception.
>
> But indeed, the following code will not raise any exception at   ptr :=
> unsafe.Pointer(rf.UnsafeAddr()).
> It indicates that unsafe.Pointer(rf.UnsafeAddr()) is safe.
>
> Anybody can help to explain this?
>
> go run -race -gcflags=all=-d=checkptr c.go
> package main
>
> import (
> "reflect"
> "unsafe"
> "fmt"
>)
>
> func main() {
> var s = struct{ foo int }{100}
>
> rs := reflect.ValueOf().Elem()
> rf := rs.Field(0)
>
>ptr := unsafe.Pointer(rf.UnsafeAddr())
>
> x := rf.UnsafeAddr()
>ptr = unsafe.Pointer(x)
>fmt.Println(ptr)
> }
>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/14da5c55-9137-46bc-90e1-b51b8ef6553bn%40googlegroups.com
> <https://groups.google.com/d/msgid/golang-nuts/14da5c55-9137-46bc-90e1-b51b8ef6553bn%40googlegroups.com?utm_medium=email_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CALS7p_eYX2_n0QFKJQFX9xVopRAKoMggQCZxhoD9AjeKrFEMXw%40mail.gmail.com.