使用http.Get()时出现死锁问题。

huangapple go评论119阅读模式
英文:

Dead block with http.Get()

问题

根据FuncOf文档:

调用任何需要事件循环的异步JavaScript API,比如fetch (http.Client),会导致立即死锁。因此,阻塞函数应该显式地启动一个新的goroutine。

所以,我写了下面的代码:

  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "net/http"
  7. "syscall/js"
  8. )
  9. func (db *DataBase) init(dataSet, table string) {
  10. var Ok, Err, Upgrade js.Func
  11. db.Request = Window.Get("indexedDB").Call("open", dataSet, 1)
  12. done := make(chan *bytes.Buffer)
  13. Upgrade = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  14. defer Upgrade.Release()
  15. db.Data = this.Get("result")
  16. fullUrlFile := "https://i.imgur.com/m1UIjW1.jpg"
  17. go func(fullUrlFile string) {
  18. var blob *bytes.Buffer
  19. r, e := http.Get(fullUrlFile)
  20. if e != nil {
  21. panic(e)
  22. }
  23. defer r.Body.Close()
  24. buildFileName()
  25. // Create blob
  26. var dest []byte
  27. blob = bytes.NewBuffer(dest)
  28. io.Copy(blob, r.Body)
  29. done <- blob
  30. }(fullUrlFile)
  31. blob := <-done
  32. Store := db.Data.Call("createObjectStore", table, map[string]interface{}{"keyPath": "id"})
  33. Store.Call("add", map[string]interface{}{"id": "00-03", "name": "Karam", "age": 19, "email": "kenny@planet.org", "image": blob})
  34. Window.Call("alert", "First record posted.")
  35. return nil
  36. })
  37. db.Request.Set("onupgradeneeded", Upgrade)
  38. }

但是仍然出现应用程序退出的死锁错误!

  1. fatal error: all goroutines are asleep - deadlock!
  2. wasm_exec.js:51
  3. wasm_exec.js:51 goroutine 1 [chan receive]:
  4. wasm_exec.js:51 main.main()
  5. wasm_exec.js:51 /home/hajsf/idb/main.go:24 +0x4
  6. wasm_exec.js:51
  7. wasm_exec.js:51 goroutine 6 [chan receive]:
  8. wasm_exec.js:51 main.(*DataBase).init.func1({{}, 0x7ff8000100000011, 0x410240}, {0x40ec80, 0x1, 0x1})
  9. wasm_exec.js:51 /home/hajsf/idb/initiate.go:57 +0xe
  10. wasm_exec.js:51 syscall/js.handleEvent()
  11. wasm_exec.js:51 /usr/local/go/src/syscall/js/func.go:96 +0x27
  12. wasm_exec.js:51
  13. wasm_exec.js:51 goroutine 7 [select]:
  14. wasm_exec.js:51 net/http.(*Transport).RoundTrip(0x324e20, 0x492000)
  15. wasm_exec.js:51 /usr/local/go/src/net/http/roundtrip_js.go:170 +0x8d
  16. wasm_exec.js:51 net/http.send(0x492000, {0xbe880, 0x324e20}, {0x0, 0x0, 0x0})
  17. wasm_exec.js:51 /usr/local/go/src/net/http/client.go:252 +0x8b
  18. wasm_exec.js:51 net/http.(*Client).send(0x334a80, 0x492000, {0x0, 0x0, 0x0})
  19. wasm_exec.js:51 /usr/local/go/src/net/http/client.go:176 +0x11
  20. wasm_exec.js:51 net/http.(*Client).do(0x334a80, 0x492000)
  21. wasm_exec.js:51 /usr/local/go/src/net/http/client.go:725 +0xb5
  22. wasm_exec.js:51 net/http.(*Client).Do(...)
  23. wasm_exec.js:51 /usr/local/go/src/net/http/client.go:593
  24. wasm_exec.js:51 net/http.(*Client).Get(0x334a80, {0x7546d, 0x1f})
  25. wasm_exec.js:51 /usr/local/go/src/net/http/client.go:480 +0xe
  26. wasm_exec.js:51 net/http.Get(...)
  27. wasm_exec.js:51 /usr/local/go/src/net/http/client.go:449
  28. wasm_exec.js:51 main.(*DataBase).init.func1.1(0x4360c0, {0x7546d, 0x1f})
  29. wasm_exec.js:51 /home/hajsf/idb/initiate.go:43 +0x4
  30. wasm_exec.js:51 created by main.(*DataBase).init.func1
  31. wasm_exec.js:51 /home/hajsf/idb/initiate.go:40 +0xd
  32. wasm_exec.js:151 exit code: 2
  33. exit @ wasm_exec.js:151
  34. runtime.wasmExit @ wasm_exec.js:275
  35. $runtime.wasmExit @ main.wasm:0xe065d
  36. $runtime.exit @ main.wasm:0xe048b
  37. $runtime.fatalthrow.func1 @ main.wasm:0x7c1a2
  38. $runtime.systemstack @ main.wasm:0xdd8f7
  39. $runtime.fatalthrow @ main.wasm:0x7bff8
  40. $runtime.throw @ main.wasm:0x7ba33
  41. $runtime.checkdead @ main.wasm:0x9bcb8
  42. $runtime.mput @ main.wasm:0x9e0f6
  43. $runtime.stopm @ main.wasm:0x8ae91
  44. $runtime.findrunnable @ main.wasm:0x8d33e
  45. $runtime.schedule @ main.wasm:0x91430
  46. $runtime.park_m @ main.wasm:0x9247f
  47. $runtime.mcall @ main.wasm:0xdd88c
  48. $runtime.gopark @ main.wasm:0x81740
  49. $runtime.selectgo @ main.wasm:0xa5c4f
  50. $net_http.__Transport_.RoundTrip @ main.wasm:0x3f3ae3
  51. $wasm_pc_f_loop @ main.wasm:0xe0444
  52. $wasm_export_resume @ main.wasm:0xe0425
  53. _resume @ wasm_exec.js:588
  54. (anonymous) @ wasm_exec.js:599
  55. IndexedDB (async)
  56. syscall/js.valueCall @ wasm_exec.js:399
  57. $syscall_js.valueCall @ main.wasm:0x14799e
  58. $syscall_js.Value.Call @ main.wasm:0x145065
  59. $main.__DataBase_.init @ main.wasm:0x479c61
  60. $main.init.0 @ main.wasm:0x47d181
  61. $runtime.doInit @ main.wasm:0xa0e3d
  62. $runtime.main @ main.wasm:0x80948
  63. $wasm_pc_f_loop @ main.wasm:0xe0444
  64. $wasm_export_run @ main.wasm:0xe0417
  65. run @ wasm_exec.js:577
  66. init @ wasm.js:7
  67. await in init (async)
  68. (anonymous) @ (index):20
  69. (anonymous) @ (index):22
  70. wasm_exec.js:586 Uncaught (in promise) Error: Go program has already exited
  71. at global.Go._resume (wasm_exec.js:586)
  72. at wasm_exec.js:599
  73. _resume @ wasm_exec.js:586
  74. (anonymous) @ wasm_exec.js:599
  75. Promise.then (async)
  76. syscall/js.valueCall @ wasm_exec.js:399
  77. $syscall_js.valueCall @ main.wasm:0x14799e
  78. $syscall_js.Value.Call @ main.wasm:0x145065
  79. $net_http.__Transport_.RoundTrip @ main.wasm:0x3f3943
  80. $wasm_pc_f_loop @ main.wasm:0xe0444
  81. $wasm_export_resume @ main.wasm:0xe0425
  82. _resume @ wasm_exec.js:588
  83. (anonymous) @ wasm_exec.js:599
  84. IndexedDB (async)
  85. syscall/js.valueCall @ wasm_exec.js:399
  86. $syscall_js.valueCall @ main.wasm:0x14799e
  87. $syscall_js.Value.Call @ main.wasm:0x145065
  88. $main.__DataBase_.init @ main.wasm:0x479c61
  89. $main.init.0 @ main.wasm:0x47d181
  90. $runtime.doInit @ main.wasm:0xa0e3d
  91. $runtime.main @ main.wasm:0x80948
  92. $wasm_pc_f_loop @ main.wasm:0xe0444
  93. $wasm_export_run @ main.wasm:0xe0417
  94. run @ wasm_exec.js:577
  95. init @ wasm.js:7
  96. await in init (async)
  97. (anonymous) @ (index):20
  98. (anonymous) @ (index):22
  99. wasm_exec.js:586 Uncaught Error: Go program has already exited
  100. at global.Go._resume (wasm_exec.js:586)
  101. at IDBOpenDBRequest.<anonymous> (wasm_exec.js:599)

有什么想法吗?

英文:

As per FuncOf documentation:

> calling any async JavaScript API, which requires the event loop, like
> fetch (http.Client), will cause an immediate deadlock. Therefore a
> blocking function should explicitly start a new goroutine.

So, I wrote the below code:

  1. package main
  2. import (
  3. &quot;bytes&quot;
  4. &quot;fmt&quot;
  5. &quot;io&quot;
  6. &quot;net/http&quot;
  7. &quot;syscall/js&quot;
  8. )
  9. func (db *DataBase) init(dataSet, table string) {
  10. var Ok, Err, Upgrade js.Func
  11. db.Request = Window.Get(&quot;indexedDB&quot;).Call(&quot;open&quot;, dataSet, 1)
  12. done := make(chan *bytes.Buffer)
  13. Upgrade = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  14. defer Upgrade.Release()
  15. db.Data = this.Get(&quot;result&quot;)
  16. fullUrlFile = &quot;https://i.imgur.com/m1UIjW1.jpg&quot;
  17. go func(fullUrlFile string) {
  18. var blob *bytes.Buffer
  19. r, e := http.Get(fullUrlFile)
  20. if e != nil {
  21. panic(e)
  22. }
  23. defer r.Body.Close()
  24. buildFileName()
  25. // Create blob
  26. var dest []byte
  27. blob = bytes.NewBuffer(dest)
  28. io.Copy(blob, r.Body)
  29. done &lt;- blob
  30. }(fullUrlFile)
  31. blob := &lt;-done
  32. Store := db.Data.Call(&quot;createObjectStore&quot;, table, map[string]interface{}{&quot;keyPath&quot;: &quot;id&quot;})
  33. Store.Call(&quot;add&quot;, map[string]interface{}{&quot;id&quot;: &quot;00-03&quot;, &quot;name&quot;: &quot;Karam&quot;, &quot;age&quot;: 19, &quot;email&quot;: &quot;kenny@planet.org&quot;, &quot;image&quot;: blob})
  34. Window.Call(&quot;alert&quot;, &quot;First record posted.&quot;)
  35. return nil
  36. })
  37. db.Request.Set(&quot;onupgradeneeded&quot;, Upgrade)
  38. }

But still getting my app exiting with dead block!

  1. fatal error: all goroutines are asleep - deadlock!
  2. wasm_exec.js:51
  3. wasm_exec.js:51 goroutine 1 [chan receive]:
  4. wasm_exec.js:51 main.main()
  5. wasm_exec.js:51 /home/hajsf/idb/main.go:24 +0x4
  6. wasm_exec.js:51
  7. wasm_exec.js:51 goroutine 6 [chan receive]:
  8. wasm_exec.js:51 main.(*DataBase).init.func1({{}, 0x7ff8000100000011, 0x410240}, {0x40ec80, 0x1, 0x1})
  9. wasm_exec.js:51 /home/hajsf/idb/initiate.go:57 +0xe
  10. wasm_exec.js:51 syscall/js.handleEvent()
  11. wasm_exec.js:51 /usr/local/go/src/syscall/js/func.go:96 +0x27
  12. wasm_exec.js:51
  13. wasm_exec.js:51 goroutine 7 [select]:
  14. wasm_exec.js:51 net/http.(*Transport).RoundTrip(0x324e20, 0x492000)
  15. wasm_exec.js:51 /usr/local/go/src/net/http/roundtrip_js.go:170 +0x8d
  16. wasm_exec.js:51 net/http.send(0x492000, {0xbe880, 0x324e20}, {0x0, 0x0, 0x0})
  17. wasm_exec.js:51 /usr/local/go/src/net/http/client.go:252 +0x8b
  18. wasm_exec.js:51 net/http.(*Client).send(0x334a80, 0x492000, {0x0, 0x0, 0x0})
  19. wasm_exec.js:51 /usr/local/go/src/net/http/client.go:176 +0x11
  20. wasm_exec.js:51 net/http.(*Client).do(0x334a80, 0x492000)
  21. wasm_exec.js:51 /usr/local/go/src/net/http/client.go:725 +0xb5
  22. wasm_exec.js:51 net/http.(*Client).Do(...)
  23. wasm_exec.js:51 /usr/local/go/src/net/http/client.go:593
  24. wasm_exec.js:51 net/http.(*Client).Get(0x334a80, {0x7546d, 0x1f})
  25. wasm_exec.js:51 /usr/local/go/src/net/http/client.go:480 +0xe
  26. wasm_exec.js:51 net/http.Get(...)
  27. wasm_exec.js:51 /usr/local/go/src/net/http/client.go:449
  28. wasm_exec.js:51 main.(*DataBase).init.func1.1(0x4360c0, {0x7546d, 0x1f})
  29. wasm_exec.js:51 /home/hajsf/idb/initiate.go:43 +0x4
  30. wasm_exec.js:51 created by main.(*DataBase).init.func1
  31. wasm_exec.js:51 /home/hajsf/idb/initiate.go:40 +0xd
  32. wasm_exec.js:151 exit code: 2
  33. exit @ wasm_exec.js:151
  34. runtime.wasmExit @ wasm_exec.js:275
  35. $runtime.wasmExit @ main.wasm:0xe065d
  36. $runtime.exit @ main.wasm:0xe048b
  37. $runtime.fatalthrow.func1 @ main.wasm:0x7c1a2
  38. $runtime.systemstack @ main.wasm:0xdd8f7
  39. $runtime.fatalthrow @ main.wasm:0x7bff8
  40. $runtime.throw @ main.wasm:0x7ba33
  41. $runtime.checkdead @ main.wasm:0x9bcb8
  42. $runtime.mput @ main.wasm:0x9e0f6
  43. $runtime.stopm @ main.wasm:0x8ae91
  44. $runtime.findrunnable @ main.wasm:0x8d33e
  45. $runtime.schedule @ main.wasm:0x91430
  46. $runtime.park_m @ main.wasm:0x9247f
  47. $runtime.mcall @ main.wasm:0xdd88c
  48. $runtime.gopark @ main.wasm:0x81740
  49. $runtime.selectgo @ main.wasm:0xa5c4f
  50. $net_http.__Transport_.RoundTrip @ main.wasm:0x3f3ae3
  51. $wasm_pc_f_loop @ main.wasm:0xe0444
  52. $wasm_export_resume @ main.wasm:0xe0425
  53. _resume @ wasm_exec.js:588
  54. (anonymous) @ wasm_exec.js:599
  55. IndexedDB (async)
  56. syscall/js.valueCall @ wasm_exec.js:399
  57. $syscall_js.valueCall @ main.wasm:0x14799e
  58. $syscall_js.Value.Call @ main.wasm:0x145065
  59. $main.__DataBase_.init @ main.wasm:0x479c61
  60. $main.init.0 @ main.wasm:0x47d181
  61. $runtime.doInit @ main.wasm:0xa0e3d
  62. $runtime.main @ main.wasm:0x80948
  63. $wasm_pc_f_loop @ main.wasm:0xe0444
  64. $wasm_export_run @ main.wasm:0xe0417
  65. run @ wasm_exec.js:577
  66. init @ wasm.js:7
  67. await in init (async)
  68. (anonymous) @ (index):20
  69. (anonymous) @ (index):22
  70. wasm_exec.js:586 Uncaught (in promise) Error: Go program has already exited
  71. at global.Go._resume (wasm_exec.js:586)
  72. at wasm_exec.js:599
  73. _resume @ wasm_exec.js:586
  74. (anonymous) @ wasm_exec.js:599
  75. Promise.then (async)
  76. syscall/js.valueCall @ wasm_exec.js:399
  77. $syscall_js.valueCall @ main.wasm:0x14799e
  78. $syscall_js.Value.Call @ main.wasm:0x145065
  79. $net_http.__Transport_.RoundTrip @ main.wasm:0x3f3943
  80. $wasm_pc_f_loop @ main.wasm:0xe0444
  81. $wasm_export_resume @ main.wasm:0xe0425
  82. _resume @ wasm_exec.js:588
  83. (anonymous) @ wasm_exec.js:599
  84. IndexedDB (async)
  85. syscall/js.valueCall @ wasm_exec.js:399
  86. $syscall_js.valueCall @ main.wasm:0x14799e
  87. $syscall_js.Value.Call @ main.wasm:0x145065
  88. $main.__DataBase_.init @ main.wasm:0x479c61
  89. $main.init.0 @ main.wasm:0x47d181
  90. $runtime.doInit @ main.wasm:0xa0e3d
  91. $runtime.main @ main.wasm:0x80948
  92. $wasm_pc_f_loop @ main.wasm:0xe0444
  93. $wasm_export_run @ main.wasm:0xe0417
  94. run @ wasm_exec.js:577
  95. init @ wasm.js:7
  96. await in init (async)
  97. (anonymous) @ (index):20
  98. (anonymous) @ (index):22
  99. wasm_exec.js:586 Uncaught Error: Go program has already exited
  100. at global.Go._resume (wasm_exec.js:586)
  101. at IDBOpenDBRequest.&lt;anonymous&gt; (wasm_exec.js:599)

Any thought?

答案1

得分: 0

我找到了,goroutine 应该覆盖整个函数范围,像这样:

  1. js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  2. go func() {
  3. [...]
  4. someBlockingFunction()
  5. [...]
  6. }()
  7. })
英文:

I found it, the goroutine should be covering the full function scope, like:

  1. js.FuncOf(func(this js.Value, args []js.Value) interface{} {
  2. go func() {
  3. [...]
  4. someBlockingFunction()
  5. [...]
  6. }()
  7. })

huangapple
  • 本文由 发表于 2021年11月18日 16:55:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/70016981.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定