diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2016-06-16 16:24:30 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-06-16 16:24:30 +0200 |
commit | 9837b12ee6063ccbee20d50aef21d1916b5af07d (patch) | |
tree | 95135211cd6d2fd313ac80612379b02ba421e07b /lib | |
parent | 87451f549d02fcf2d03a899f336f9dbbf914bd00 (diff) | |
parent | 974dcc87666a42ee6a4fea197df65956398d7ae1 (diff) | |
download | Nim-9837b12ee6063ccbee20d50aef21d1916b5af07d.tar.gz |
Merge pull request #4336 from cheatfate/protectwinrw
Implement protection on callback environment.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/asyncdispatch.nim | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index c5b516b39..455bebc7f 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() @@ -524,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: @@ -1026,6 +1038,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: |