From 11d9b15fc49bc229ee2881f48c52bb7b75d0ee96 Mon Sep 17 00:00:00 2001 From: cheatfate Date: Tue, 14 Jun 2016 21:23:48 +0300 Subject: Implement protection on callback environment. --- lib/pure/asyncdispatch.nim | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'lib/pure') diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 82166902f..1e6db2a33 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -434,6 +434,9 @@ when defined(windows) or defined(nimdoc): fd*: AsyncFD # TODO: Rename this. cb*: proc (fd: AsyncFD, bytesTransferred: Dword, errcode: OSErrorCode) {.closure,gcsafe.} + cell*: ForeignCell # we need this `cell` to protect our `cb` environment, + # when using RegisterWaitForSingleObject, because + # waiting is done in different thread. PDispatcher* = ref object of PDispatcherBase ioPort: Handle @@ -517,6 +520,13 @@ when defined(windows) or defined(nimdoc): customOverlapped.data.cb(customOverlapped.data.fd, lpNumberOfBytesTransferred, OSErrorCode(-1)) + + # If cell.data != nil, then system.protect(rawEnv(cb)) was called, + # so we need to dispose our `cb` environment, because it is not needed + # anymore. + if customOverlapped.data.cell.data != nil: + system.dispose(customOverlapped.data.cell) + GC_unref(customOverlapped) else: let errCode = osLastError() @@ -1026,6 +1036,10 @@ when defined(windows) or defined(nimdoc): # poll() GC_ref(pcd.ovl) ) + # We need to protect our callback environment value, so GC will not free it + # accidentally. + ol.data.cell = system.protect(rawEnv(ol.data.cb)) + # This is main part of `hacky way` is using WSAEventSelect, so `hEvent` # will be signaled when appropriate `mask` events will be triggered. if wsaEventSelect(fd.SocketHandle, hEvent, mask) != 0: -- cgit 1.4.1-2-gfad0 From 974dcc87666a42ee6a4fea197df65956398d7ae1 Mon Sep 17 00:00:00 2001 From: cheatfate Date: Tue, 14 Jun 2016 22:33:15 +0300 Subject: One more place to release callback environment protection --- lib/pure/asyncdispatch.nim | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/pure') diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 1e6db2a33..8ba4b5cca 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -534,6 +534,8 @@ when defined(windows) or defined(nimdoc): assert customOverlapped.data.fd == lpCompletionKey.AsyncFD customOverlapped.data.cb(customOverlapped.data.fd, lpNumberOfBytesTransferred, errCode) + if customOverlapped.data.cell.data != nil: + system.dispose(customOverlapped.data.cell) GC_unref(customOverlapped) else: if errCode.int32 == WAIT_TIMEOUT: -- cgit 1.4.1-2-gfad0