{"action":"created","issue":{"url":"https://api.github.com/repos/mono/mono/issues/2593","repository_url":"https://api.github.com/repos/mono/mono","labels_url":"https://api.github.com/repos/mono/mono/issues/2593/labels{/name}","comments_url":"https://api.github.com/repos/mono/mono/issues/2593/comments","events_url":"https://api.github.com/repos/mono/mono/issues/2593/events","html_url":"https://github.com/mono/mono/pull/2593","id":132743775,"number":2593,"title":"[coop] Fix native-to-managed wrapper thread attach","user":{"login":"ludovic-henry","id":660779,"avatar_url":"https://avatars.githubusercontent.com/u/660779?v=3","gravatar_id":"","url":"https://api.github.com/users/ludovic-henry","html_url":"https://github.com/ludovic-henry","followers_url":"https://api.github.com/users/ludovic-henry/followers","following_url":"https://api.github.com/users/ludovic-henry/following{/other_user}","gists_url":"https://api.github.com/users/ludovic-henry/gists{/gist_id}","starred_url":"https://api.github.com/users/ludovic-henry/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ludovic-henry/subscriptions","organizations_url":"https://api.github.com/users/ludovic-henry/orgs","repos_url":"https://api.github.com/users/ludovic-henry/repos","events_url":"https://api.github.com/users/ludovic-henry/events{/privacy}","received_events_url":"https://api.github.com/users/ludovic-henry/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2016-02-10T16:13:20Z","updated_at":"2016-02-11T04:10:55Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/mono/mono/pulls/2593","html_url":"https://github.com/mono/mono/pull/2593","diff_url":"https://github.com/mono/mono/pull/2593.diff","patch_url":"https://github.com/mono/mono/pull/2593.patch"},"body":"Previously, when we would invoke a native-to-managed wrapper from a thread that has not been attached to the runtime, we would simply ensure to attach this thread to the runtime. The issue arise when using coop and needing to switch a thread which is not executing runtime or managed code to BLOCKING state.\r\n\r\nThat would arise on iOS when using dispatch_async:\r\n - the user would enqueue a Delegate, triggering a call to mono_delegate_to_ftnptr, generating this native-to-managed wrapper\r\n - the wrapper would be called asynchronously on a thread managed by the OS/dispatch_async\r\n - the thread would attach to the runtime, switching its state from STARTING -> RUNNING\r\n - the thread would finish executing the delegate, thus 'detaching' from the runtime, but without switching its state from RUNNING -> BLOCKING\r\n - during the next garbage collection, the GC would try to suspend this thread as it is still in RUNNING state, but because it's neither executing runtime code, neither managed code, it will never hit a safepoint, leading to a timeouting suspend.\r\n\r\nTo fix that issue, we need to support the following state switches:\r\n - STARTING -> RUNNING -> BLOCKING: happens when it's the first time this thread calls a native-to-managed wrapper\r\n - BLOCKING -> RUNNING -> BLOCKING: happens when it's not the first time this thread is called from a facility like dispatch_async, or if it is, for example, called as a callback from an external library\r\n - RUNNING -> RUNNING -> RUNNING: if we call this wrapper from runtime or managed code, see for example System.Reflection.Emit.ILGeneratorTest.TestEmitCalliWithNullReturnType\r\n\r\nThis facility also need to take care of the current domain, to ensure that we switch properly between domains, and set it to the one that was used when creating this delegate, then restoring the original one."},"comment":{"url":"https://api.github.com/repos/mono/mono/issues/comments/182694158","html_url":"https://github.com/mono/mono/pull/2593#issuecomment-182694158","issue_url":"https://api.github.com/repos/mono/mono/issues/2593","id":182694158,"user":{"login":"lewurm","id":75403,"avatar_url":"https://avatars.githubusercontent.com/u/75403?v=3","gravatar_id":"","url":"https://api.github.com/users/lewurm","html_url":"https://github.com/lewurm","followers_url":"https://api.github.com/users/lewurm/followers","following_url":"https://api.github.com/users/lewurm/following{/other_user}","gists_url":"https://api.github.com/users/lewurm/gists{/gist_id}","starred_url":"https://api.github.com/users/lewurm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lewurm/subscriptions","organizations_url":"https://api.github.com/users/lewurm/orgs","repos_url":"https://api.github.com/users/lewurm/repos","events_url":"https://api.github.com/users/lewurm/events{/privacy}","received_events_url":"https://api.github.com/users/lewurm/received_events","type":"User","site_admin":false},"created_at":"2016-02-11T04:10:55Z","updated_at":"2016-02-11T04:10:55Z","body":"`<botmode>`\nBenchmark results: http://xamarin.github.io/benchmarker/front-end/pullrequest.html#id=60\nbuildbot logs: https://performancebot.mono-project.com/builders/debian-amd64_benchmarker_pullrequest_auto-sgen-conc-noturbo-binary/builds/16\n`</botmode>`"}}