If you try to develop a plugin locally and the method you invoke returns an error, it your application will crash. When to invoke the same plugin that is versioned, you won't crash.
Also interestingly, I am unable to catch errors when invoking platform methods using try/catch.
Flutter 1.5.8 • channel dev • https://github.com/flutter/flutter.git
Framework • revision 0ba67226ee (3 weeks ago) • 2019-04-24 17:18:28 -0700
Engine • revision c63d1cf9c9
Tools • Dart 2.3.0 (build 2.3.0-dev.0.1 1f1592edce)
github.com/go-flutter-desktop/plugins/shared_preferences v0.4.0
module github.com/drdgvhbh/gitone/desktop
go 1.12
require (
github.com/go-flutter-desktop/go-flutter v0.15.0
github.com/go-flutter-desktop/plugins/shared_preferences v0.4.0
github.com/pkg/errors v0.8.1
)
replace github.com/go-flutter-desktop/plugins/shared_preferences => /home/drd/go/src/github.com/go-flutter-desktop/plugins/shared_preferences
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7f65fe420636]
runtime stack:
runtime.throw(0x607a46, 0x2a)
/usr/local/go/src/runtime/panic.go:617 +0x72
runtime.sigpanic()
/usr/local/go/src/runtime/signal_unix.go:374 +0x4a9
goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x593120, 0xc0000abc30, 0x0)
/usr/local/go/src/runtime/cgocall.go:128 +0x5b fp=0xc0000abc00 sp=0xc0000abbc8 pc=0x40dc4b
github.com/go-flutter-desktop/go-flutter/embedder._Cfunc_FlutterEngineSendPlatformMessageResponse(0x22ea860, 0x23c6640, 0x22e95c0, 0x1f, 0x0)
_cgo_gotypes.go:274 +0x4d fp=0xc0000abc30 sp=0xc0000abc00 pc=0x4f638d
github.com/go-flutter-desktop/go-flutter/embedder.(*FlutterEngine).SendPlatformMessageResponse.func1(0xc000120000, 0x23c6640, 0xc0000c4080, 0x1f, 0x40, 0xc000000000)
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/embedder/embedder.go:244 +0xe6 fp=0xc0000abc80 sp=0xc0000abc30 pc=0x4f7fd6
github.com/go-flutter-desktop/go-flutter/embedder.(*FlutterEngine).SendPlatformMessageResponse(0xc000120000, 0x23c6640, 0xc0000c4080, 0x1f, 0x40, 0xc0000abd18)
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/embedder/embedder.go:244 +0x53 fp=0xc0000abcc0 sp=0xc0000abc80 pc=0x4f75c3
github.com/go-flutter-desktop/go-flutter.responseSender.Send.func1()
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/messenger.go:108 +0x5b fp=0xc0000abd28 sp=0xc0000abcc0 pc=0x532b8b
github.com/go-flutter-desktop/go-flutter/internal/tasker.(*Tasker).ExecuteTasks(0xc00009c090)
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/internal/tasker/tasker.go:39 +0x33 fp=0xc0000abd70 sp=0xc0000abd28 pc=0x4f8923
github.com/go-flutter-desktop/go-flutter.(*Application).Run(0xc0000a4210, 0x0, 0x0)
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/application.go:192 +0x97e fp=0xc0000abed0 sp=0xc0000abd70 pc=0x52dbce
github.com/go-flutter-desktop/go-flutter.Run(0xc000086210, 0x5, 0x6, 0x3, 0xc0000abf78)
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/application.go:23 +0x4d fp=0xc0000abf00 sp=0xc0000abed0 pc=0x52cf0d
main.main()
/home/drd/Documents/Projects/GitOne/gitone/desktop/cmd/main.go:24 +0x189 fp=0xc0000abf98 sp=0xc0000abf00 pc=0x581669
runtime.main()
/usr/local/go/src/runtime/proc.go:200 +0x20c fp=0xc0000abfe0 sp=0xc0000abf98 pc=0x43744c
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1337 +0x1 fp=0xc0000abfe8 sp=0xc0000abfe0 pc=0x4615e1
goroutine 19 [select]:
github.com/syndtr/goleveldb/leveldb/util.(*BufferPool).drain(0xc00012a000)
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/util/buffer_pool.go:206 +0x121
created by github.com/syndtr/goleveldb/leveldb/util.NewBufferPool
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/util/buffer_pool.go:237 +0x176
goroutine 35 [select]:
github.com/syndtr/goleveldb/leveldb.(*DB).compactionError(0xc0001241a0)
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db_compaction.go:90 +0xcd
created by github.com/syndtr/goleveldb/leveldb.openDB
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db.go:142 +0x40f
goroutine 36 [select]:
github.com/syndtr/goleveldb/leveldb.(*DB).mpoolDrain(0xc0001241a0)
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db_state.go:101 +0xf6
created by github.com/syndtr/goleveldb/leveldb.openDB
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db.go:143 +0x431
goroutine 37 [select]:
github.com/syndtr/goleveldb/leveldb.(*DB).tCompaction(0xc0001241a0)
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db_compaction.go:825 +0x23a
created by github.com/syndtr/goleveldb/leveldb.openDB
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db.go:149 +0x585
goroutine 38 [select]:
github.com/syndtr/goleveldb/leveldb.(*DB).mCompaction(0xc0001241a0)
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db_compaction.go:762 +0x12e
created by github.com/syndtr/goleveldb/leveldb.openDB
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db.go:150 +0x5a7
goroutine 6 [chan receive]:
github.com/go-flutter-desktop/go-flutter/internal/tasker.(*Tasker).Do(0xc00009c090, 0xc0000a0100)
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/internal/tasker/tasker.go:31 +0x8d
created by github.com/go-flutter-desktop/go-flutter.responseSender.Send
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/messenger.go:107 +0xe0
Lost connection to device.
github.com/go-flutter-desktop/plugins/shared_preferences in your go source foldergithub.com/go-flutter-desktop/plugins/shared_preferences v0.4.0 replace github.com/go-flutter-desktop/plugins/shared_preferences => /home/drd/go/src/github.com/go-flutter-desktop/plugins/shared_preferencesimport 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class InvokeButton extends StatelessWidget {
static const platform =
const MethodChannel('plugins.flutter.io/shared_preferences');
@override
Widget build(BuildContext context) {
return MaterialButton(
child: Text("Invoke me"),
onPressed: () async => await _invoke());
}
Future<void> _invoke() async {
debugPrint('testing');
try {
var result = await platform.invokeMethod("remove", "i am a bad argument");
debugPrint(result);
} catch (err) {
debugPrint("Error" + err);
}
}
}
Regarding
unable to catch errors when invoking platform methods using try/catch.
I think it is related to what is described here.
And for
If you try to develop a plugin locally and the method you invoke returns an error, it your application will crash. When to invoke the same plugin that is versioned, you won't crash.
I cannot reproduce the error described error, on my pc... it dosn't crash.
I am getting the folowing output (The error is expected since there is a misuse of a plugin platform message)
flutter: testing
go-flutter: no method handler registered for method 'SystemSound.play' on channel 'flutter/platform'
go-flutter: recovered from panic while handling call for method 'remove' on channel 'plugins.flutter.io/shared_preferences': interface conversion: interface {} is string, not map[interface {}]interface {}
goroutine 41 [running]:
runtime/debug.Stack(0xcd, 0x0, 0x0)
/usr/lib/go/src/runtime/debug/stack.go:24 +0x9d
runtime/debug.PrintStack()
/usr/lib/go/src/runtime/debug/stack.go:16 +0x22
github.com/go-flutter-desktop/go-flutter/plugin.(*MethodChannel).handleMethodCall.func1(0xc000564b48, 0x6, 0x5a9080, 0xc0000132b0, 0xc000140190)
/home/drakirus/lab/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/plugin/method-channel.go:155 +0x159
panic(0x5b9a80, 0xc000592180)
/usr/lib/go/src/runtime/panic.go:522 +0x1b5
github.com/go-flutter-desktop/plugins/shared_preferences.(*SharedPreferencesPlugin).handleRemove(0xc000088240, 0x5a9080, 0xc0000132b0, 0x45da90, 0x28, 0xc000569da0, 0x0)
/home/drakirus/lab/go/src/github.com/go-flutter-desktop/plugins/shared_preferences/plugin.go:106 +0x1e0
github.com/go-flutter-desktop/go-flutter/plugin.MethodHandlerFunc.HandleMethod(0xc000012360, 0x5a9080, 0xc0000132b0, 0x6, 0x5a9080, 0xc0000132b0, 0xc000140190)
/home/drakirus/lab/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/plugin/method-handler.go:17 +0x3a
github.com/go-flutter-desktop/go-flutter/plugin.(*MethodChannel).handleMethodCall(0xc000140190, 0x627f00, 0xc000012360, 0xc000564b48, 0x6, 0x5a9080, 0xc0000132b0, 0x627ea0, 0xc0005943c0)
/home/drakirus/lab/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/plugin/method-channel.go:159 +0xc7
created by github.com/go-flutter-desktop/go-flutter/plugin.(*MethodChannel).handleChannelMessage
/home/drakirus/lab/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/plugin/method-channel.go:143 +0x261
Using the folowing go.mod
module github.com/go-flutter-desktop/examples/pointer_demo/desktop
go 1.12
require (
github.com/go-flutter-desktop/go-flutter v0.16.0
github.com/go-flutter-desktop/plugins/shared_preferences v0.4.0
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/pkg/errors v0.8.1
github.com/stretchr/objx v0.2.0 // indirect
)
replace github.com/go-flutter-desktop/plugins/shared_preferences => /home/drakirus/lab/go/src/github.com/go-flutter-desktop/plugins/shared_preferences
I am experiencing this same crash when returning some error from the Go plugin side. I am also using the replace keyword to develop the plugin locally.
Are there any workarounds to overcome this issue?
I digged a bit in the source code and I found this in method-channel.go
func (m *MethodChannel) handleMethodCall(handler MethodHandler, methodCall MethodCall, responseSender ResponseSender) {
defer func() {
p := recover()
if p != nil {
fmt.Printf("go-flutter: recovered from panic while handling call for method '%s' on channel '%s': %v\n", methodCall.Method, m.channelName, p)
debug.PrintStack()
}
}()
reply, err := handler.HandleMethod(methodCall.Arguments)
if err != nil {
fmt.Printf("go-flutter: handler for method '%s' on channel '%s' returned an error: %v\n", methodCall.Method, m.channelName, err)
binaryReply, err := m.methodCodec.EncodeErrorEnvelope("error", err.Error(), nil)
if err != nil {
fmt.Printf("go-flutter: failed to encode error envelope for method '%s' on channel '%s', error: %v\n", methodCall.Method, m.channelName, err)
}
responseSender.Send(binaryReply)
}
binaryReply, err := m.methodCodec.EncodeSuccessEnvelope(reply)
if err != nil {
fmt.Printf("go-flutter: failed to encode success envelope for method '%s' on channel '%s', error: %v\n", methodCall.Method, m.channelName, err)
}
responseSender.Send(binaryReply)
}
Shouldn't the last block be in an else statement? If handler.HandleMethod returns an error, 2 responses are being sent, which causes the error from this issue. I tried it with the else and it works as expected.
Is it a bug?
@davidmartos96 I think you are right!
It does look like a bug!
Can you craft a quick pull request?
@Drakirus I just created a PR #174
I was able to reproduce the error.
First of:
var result = await platform.invokeMethod("remove", "i am a bad argument");
Will generate a panic since this cast isn't correct.
The following output is to be expected since there is a misuse of a plugin.
flutter: testing
go-flutter: no method handler registered for method 'SystemSound.play' on channel 'flutter/platform'
go-flutter: recovered from panic while handling call for method 'remove' on channel 'plugins.flutter.io/shared_preferences': interface conversion: interface {} is string, not map[interface {}]interface {}
goroutine 41 [running]:
runtime/debug.Stack(0xcd, 0x0, 0x0)
/usr/lib/go/src/runtime/debug/stack.go:24 +0x9d
runtime/debug.PrintStack()
/usr/lib/go/src/runtime/debug/stack.go:16 +0x22
github.com/go-flutter-desktop/go-flutter/plugin.(*MethodChannel).handleMethodCall.func1(0xc000564b48, 0x6, 0x5a9080, 0xc0000132b0, 0xc000140190)
/home/drakirus/lab/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/plugin/method-channel.go:155 +0x159
panic(0x5b9a80, 0xc000592180)
/usr/lib/go/src/runtime/panic.go:522 +0x1b5
github.com/go-flutter-desktop/plugins/shared_preferences.(*SharedPreferencesPlugin).handleRemove(0xc000088240, 0x5a9080, 0xc0000132b0, 0x45da90, 0x28, 0xc000569da0, 0x0)
/home/drakirus/lab/go/src/github.com/go-flutter-desktop/plugins/shared_preferences/plugin.go:106 +0x1e0
github.com/go-flutter-desktop/go-flutter/plugin.MethodHandlerFunc.HandleMethod(0xc000012360, 0x5a9080, 0xc0000132b0, 0x6, 0x5a9080, 0xc0000132b0, 0xc000140190)
/home/drakirus/lab/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/plugin/method-handler.go:17 +0x3a
github.com/go-flutter-desktop/go-flutter/plugin.(*MethodChannel).handleMethodCall(0xc000140190, 0x627f00, 0xc000012360, 0xc000564b48, 0x6, 0x5a9080, 0xc0000132b0, 0x627ea0, 0xc0005943c0)
/home/drakirus/lab/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/plugin/method-channel.go:159 +0xc7
created by github.com/go-flutter-desktop/go-flutter/plugin.(*MethodChannel).handleChannelMessage
/home/drakirus/lab/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/plugin/method-channel.go:143 +0x261
go-flutter will recover the panic and resume normal execution.
I was unable to reproduce the
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7f65fe420636]
runtime stack:
runtime.throw(0x607a46, 0x2a)
/usr/local/go/src/runtime/panic.go:617 +0x72
runtime.sigpanic()
/usr/local/go/src/runtime/signal_unix.go:374 +0x4a9
goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x593120, 0xc0000abc30, 0x0)
/usr/local/go/src/runtime/cgocall.go:128 +0x5b fp=0xc0000abc00 sp=0xc0000abbc8 pc=0x40dc4b
github.com/go-flutter-desktop/go-flutter/embedder._Cfunc_FlutterEngineSendPlatformMessageResponse(0x22ea860, 0x23c6640, 0x22e95c0, 0x1f, 0x0)
_cgo_gotypes.go:274 +0x4d fp=0xc0000abc30 sp=0xc0000abc00 pc=0x4f638d
github.com/go-flutter-desktop/go-flutter/embedder.(*FlutterEngine).SendPlatformMessageResponse.func1(0xc000120000, 0x23c6640, 0xc0000c4080, 0x1f, 0x40, 0xc000000000)
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/embedder/embedder.go:244 +0xe6 fp=0xc0000abc80 sp=0xc0000abc30 pc=0x4f7fd6
github.com/go-flutter-desktop/go-flutter/embedder.(*FlutterEngine).SendPlatformMessageResponse(0xc000120000, 0x23c6640, 0xc0000c4080, 0x1f, 0x40, 0xc0000abd18)
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/embedder/embedder.go:244 +0x53 fp=0xc0000abcc0 sp=0xc0000abc80 pc=0x4f75c3
github.com/go-flutter-desktop/go-flutter.responseSender.Send.func1()
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/messenger.go:108 +0x5b fp=0xc0000abd28 sp=0xc0000abcc0 pc=0x532b8b
github.com/go-flutter-desktop/go-flutter/internal/tasker.(*Tasker).ExecuteTasks(0xc00009c090)
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/internal/tasker/tasker.go:39 +0x33 fp=0xc0000abd70 sp=0xc0000abd28 pc=0x4f8923
github.com/go-flutter-desktop/go-flutter.(*Application).Run(0xc0000a4210, 0x0, 0x0)
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/application.go:192 +0x97e fp=0xc0000abed0 sp=0xc0000abd70 pc=0x52dbce
github.com/go-flutter-desktop/go-flutter.Run(0xc000086210, 0x5, 0x6, 0x3, 0xc0000abf78)
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/application.go:23 +0x4d fp=0xc0000abf00 sp=0xc0000abed0 pc=0x52cf0d
main.main()
/home/drd/Documents/Projects/GitOne/gitone/desktop/cmd/main.go:24 +0x189 fp=0xc0000abf98 sp=0xc0000abf00 pc=0x581669
runtime.main()
/usr/local/go/src/runtime/proc.go:200 +0x20c fp=0xc0000abfe0 sp=0xc0000abf98 pc=0x43744c
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1337 +0x1 fp=0xc0000abfe8 sp=0xc0000abfe0 pc=0x4615e1
goroutine 19 [select]:
github.com/syndtr/goleveldb/leveldb/util.(*BufferPool).drain(0xc00012a000)
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/util/buffer_pool.go:206 +0x121
created by github.com/syndtr/goleveldb/leveldb/util.NewBufferPool
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/util/buffer_pool.go:237 +0x176
goroutine 35 [select]:
github.com/syndtr/goleveldb/leveldb.(*DB).compactionError(0xc0001241a0)
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db_compaction.go:90 +0xcd
created by github.com/syndtr/goleveldb/leveldb.openDB
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db.go:142 +0x40f
goroutine 36 [select]:
github.com/syndtr/goleveldb/leveldb.(*DB).mpoolDrain(0xc0001241a0)
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db_state.go:101 +0xf6
created by github.com/syndtr/goleveldb/leveldb.openDB
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db.go:143 +0x431
goroutine 37 [select]:
github.com/syndtr/goleveldb/leveldb.(*DB).tCompaction(0xc0001241a0)
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db_compaction.go:825 +0x23a
created by github.com/syndtr/goleveldb/leveldb.openDB
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db.go:149 +0x585
goroutine 38 [select]:
github.com/syndtr/goleveldb/leveldb.(*DB).mCompaction(0xc0001241a0)
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db_compaction.go:762 +0x12e
created by github.com/syndtr/goleveldb/leveldb.openDB
/home/drd/go/pkg/mod/github.com/syndtr/[email protected]/leveldb/db.go:150 +0x5a7
goroutine 6 [chan receive]:
github.com/go-flutter-desktop/go-flutter/internal/tasker.(*Tasker).Do(0xc00009c090, 0xc0000a0100)
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/internal/tasker/tasker.go:31 +0x8d
created by github.com/go-flutter-desktop/go-flutter.responseSender.Send
/home/drd/go/pkg/mod/github.com/go-flutter-desktop/[email protected]/messenger.go:107 +0xe0
Lost connection to device.
and I kind of let the issue aside :-1:
Thanks to @davidmartos96 this issue was fixed.
The error wasn't about misuse of plugins but about errors thrown by plugins.
The regression was introduced during the v0.11.0 release. The handleMethodCall function should return earlier.
I should of try to dig a little bit deeper when I looked at the issue (by asking questions). This error was serious, and I didn't realized,.. my bad.
Ohh,
You are now able to catch PlatformException using try/catch!
@Drakirus I came across this issue while porting a plugin that threw some handled errors from the native side. Returning nil, err wasn't working correctly...
:+1:
Just out of curiosity, what is the plugin you are porting to go-flutter?
@Drakirus It is sqflite. I almost have it, although I don't really know how to make it behave the same way as the iOS and Android implementations. In Android it uses Handler.post(runnable) to make some operation in the background and then it posts the response back to the main thread to call Result.success(someResult). The handler function it quickly finishes because it leaves the operation to the background thread. When running in Go, the handle functions for each DB operation are blocking...
When running in Go, the handle functions for each DB operation are blocking...
If you are using HandleFuncSync the operation will block the Main Thread.
But using HandleFunc, the operation are run on a background thread.
@Drakirus Yes, I was already using HandleFunc. I found the issue though. I was comparing the performance of the sqlite library on the android emulator vs go-flutter. It looks like the encoding and decoding performance of the platform calls is much worse in go-flutter.
1 INSERT (time since the call to invokeMethod in Dart until the reply is received in Dart)
Android emulator -> 1 ms
Go Flutter -> 30 ms
Quite different performance right?
The time it takes to make the actual INSERT measured in the native side is 100 us in both platforms.
Is this a known limitation of the project? Awesome project BTW :)
@davidmartos96 thanks for the feedback.
The encoding and decoding performance should be as good as on Android, Golang is Fast.
I'm pretty sure the 30ms comes from the MainLoop.
The flutter engine team added FlutterEngineFlushPendingTasksNow as a workaround for embedders to flush tasks (platform messages) on threads where the engine didn't own the message loop (or couldn't interact with the same as is the case on Android and iOS).
On go-flutter, we could use PollEvents to have an instant feedback platform messages, but that would result in high CPU load.
In order to reduce CPU load we choose to wait 16ms in order to get the 60fps-ish iterations while having the possibility to fetch platforms messages when no pending frames are to be swapped.
I assume the 30ms delay you are experiencing comes from 2 loop cycles, one to get the platform message and issuing the task into a specific goroutine; and one to return the message to Dart.
Most helpful comment
@Drakirus I just created a PR #174