Merge pull request #4336 from cheatfate/protectwinrw

Implement protection on callback environment.
This commit is contained in:
Andreas Rumpf 2016-06-16 16:24:30 +02:00 • committed by GitHub
commit 9837b12ee6

View file

@ -434,6 +434,9 @@ when defined(windows) or defined(nimdoc):
fd*: AsyncFD # TODO: Rename this. fd*: AsyncFD # TODO: Rename this.
cb*: proc (fd: AsyncFD, bytesTransferred: Dword, cb*: proc (fd: AsyncFD, bytesTransferred: Dword,
errcode: OSErrorCode) {.closure,gcsafe.} 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 PDispatcher* = ref object of PDispatcherBase
ioPort: Handle ioPort: Handle
@ -517,6 +520,13 @@ when defined(windows) or defined(nimdoc):
customOverlapped.data.cb(customOverlapped.data.fd, customOverlapped.data.cb(customOverlapped.data.fd,
lpNumberOfBytesTransferred, OSErrorCode(-1)) 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) GC_unref(customOverlapped)
else: else:
let errCode = osLastError() let errCode = osLastError()
@ -524,6 +534,8 @@ when defined(windows) or defined(nimdoc):
assert customOverlapped.data.fd == lpCompletionKey.AsyncFD assert customOverlapped.data.fd == lpCompletionKey.AsyncFD
customOverlapped.data.cb(customOverlapped.data.fd, customOverlapped.data.cb(customOverlapped.data.fd,
lpNumberOfBytesTransferred, errCode) lpNumberOfBytesTransferred, errCode)
if customOverlapped.data.cell.data != nil:
system.dispose(customOverlapped.data.cell)
GC_unref(customOverlapped) GC_unref(customOverlapped)
else: else:
if errCode.int32 == WAIT_TIMEOUT: if errCode.int32 == WAIT_TIMEOUT:
@ -1026,6 +1038,10 @@ when defined(windows) or defined(nimdoc):
# poll() # poll()
GC_ref(pcd.ovl) 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` # This is main part of `hacky way` is using WSAEventSelect, so `hEvent`
# will be signaled when appropriate `mask` events will be triggered. # will be signaled when appropriate `mask` events will be triggered.
if wsaEventSelect(fd.SocketHandle, hEvent, mask) != 0: if wsaEventSelect(fd.SocketHandle, hEvent, mask) != 0: