asyncdispatch exception memory leaks fixes.
This commit is contained in:
parent
4b95819146
commit
e84efc4d01
2 changed files with 41 additions and 29 deletions
|
|
@ -871,7 +871,9 @@ when defined(windows) or defined(nimdoc):
|
||||||
if unregisterWait(pcd.waitFd) == 0:
|
if unregisterWait(pcd.waitFd) == 0:
|
||||||
let err = osLastError()
|
let err = osLastError()
|
||||||
if err.int32 != ERROR_IO_PENDING:
|
if err.int32 != ERROR_IO_PENDING:
|
||||||
raiseOSError(osLastError())
|
deallocShared(cast[pointer](pcd))
|
||||||
|
discard wsaCloseEvent(hEvent)
|
||||||
|
raiseOSError(err)
|
||||||
if cb(fd):
|
if cb(fd):
|
||||||
# callback returned `true`, so we free all allocated resources
|
# callback returned `true`, so we free all allocated resources
|
||||||
deallocShared(cast[pointer](pcd))
|
deallocShared(cast[pointer](pcd))
|
||||||
|
|
@ -895,9 +897,10 @@ when defined(windows) or defined(nimdoc):
|
||||||
cast[WAITORTIMERCALLBACK](waitableCallback),
|
cast[WAITORTIMERCALLBACK](waitableCallback),
|
||||||
cast[pointer](pcd), INFINITE, flags):
|
cast[pointer](pcd), INFINITE, flags):
|
||||||
# pcd.ovl will be unrefed in poll()
|
# pcd.ovl will be unrefed in poll()
|
||||||
|
let err = osLastError()
|
||||||
discard wsaCloseEvent(hEvent)
|
discard wsaCloseEvent(hEvent)
|
||||||
deallocShared(cast[pointer](pcd))
|
deallocShared(cast[pointer](pcd))
|
||||||
raiseOSError(osLastError())
|
raiseOSError(err)
|
||||||
else:
|
else:
|
||||||
# we incref `pcd.ovl` and `protect` callback one more time,
|
# we incref `pcd.ovl` and `protect` callback one more time,
|
||||||
# because it will be unrefed and disposed in `poll()` after
|
# because it will be unrefed and disposed in `poll()` after
|
||||||
|
|
@ -912,19 +915,21 @@ when defined(windows) or defined(nimdoc):
|
||||||
# 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:
|
||||||
|
let err = osLastError()
|
||||||
GC_unref(ol)
|
GC_unref(ol)
|
||||||
deallocShared(cast[pointer](pcd))
|
deallocShared(cast[pointer](pcd))
|
||||||
discard wsaCloseEvent(hEvent)
|
discard wsaCloseEvent(hEvent)
|
||||||
raiseOSError(osLastError())
|
raiseOSError(err)
|
||||||
|
|
||||||
pcd.ovl = ol
|
pcd.ovl = ol
|
||||||
if not registerWaitForSingleObject(addr(pcd.waitFd), hEvent,
|
if not registerWaitForSingleObject(addr(pcd.waitFd), hEvent,
|
||||||
cast[WAITORTIMERCALLBACK](waitableCallback),
|
cast[WAITORTIMERCALLBACK](waitableCallback),
|
||||||
cast[pointer](pcd), INFINITE, flags):
|
cast[pointer](pcd), INFINITE, flags):
|
||||||
|
let err = osLastError()
|
||||||
GC_unref(ol)
|
GC_unref(ol)
|
||||||
deallocShared(cast[pointer](pcd))
|
deallocShared(cast[pointer](pcd))
|
||||||
discard wsaCloseEvent(hEvent)
|
discard wsaCloseEvent(hEvent)
|
||||||
raiseOSError(osLastError())
|
raiseOSError(err)
|
||||||
p.handles.incl(fd)
|
p.handles.incl(fd)
|
||||||
|
|
||||||
proc addRead*(fd: AsyncFD, cb: Callback) =
|
proc addRead*(fd: AsyncFD, cb: Callback) =
|
||||||
|
|
|
||||||
|
|
@ -856,7 +856,9 @@ when defined(windows) or defined(nimdoc):
|
||||||
if unregisterWait(pcd.waitFd) == 0:
|
if unregisterWait(pcd.waitFd) == 0:
|
||||||
let err = osLastError()
|
let err = osLastError()
|
||||||
if err.int32 != ERROR_IO_PENDING:
|
if err.int32 != ERROR_IO_PENDING:
|
||||||
raiseOSError(osLastError())
|
deallocShared(cast[pointer](pcd))
|
||||||
|
discard wsaCloseEvent(hEvent)
|
||||||
|
raiseOSError(err)
|
||||||
if cb(fd):
|
if cb(fd):
|
||||||
# callback returned `true`, so we free all allocated resources
|
# callback returned `true`, so we free all allocated resources
|
||||||
deallocShared(cast[pointer](pcd))
|
deallocShared(cast[pointer](pcd))
|
||||||
|
|
@ -880,9 +882,10 @@ when defined(windows) or defined(nimdoc):
|
||||||
cast[WAITORTIMERCALLBACK](waitableCallback),
|
cast[WAITORTIMERCALLBACK](waitableCallback),
|
||||||
cast[pointer](pcd), INFINITE, flags):
|
cast[pointer](pcd), INFINITE, flags):
|
||||||
# pcd.ovl will be unrefed in poll()
|
# pcd.ovl will be unrefed in poll()
|
||||||
discard wsaCloseEvent(hEvent)
|
let err = osLastError()
|
||||||
deallocShared(cast[pointer](pcd))
|
deallocShared(cast[pointer](pcd))
|
||||||
raiseOSError(osLastError())
|
discard wsaCloseEvent(hEvent)
|
||||||
|
raiseOSError(err)
|
||||||
else:
|
else:
|
||||||
# we incref `pcd.ovl` and `protect` callback one more time,
|
# we incref `pcd.ovl` and `protect` callback one more time,
|
||||||
# because it will be unrefed and disposed in `poll()` after
|
# because it will be unrefed and disposed in `poll()` after
|
||||||
|
|
@ -897,19 +900,21 @@ when defined(windows) or defined(nimdoc):
|
||||||
# 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:
|
||||||
|
let err = osLastError()
|
||||||
GC_unref(ol)
|
GC_unref(ol)
|
||||||
deallocShared(cast[pointer](pcd))
|
deallocShared(cast[pointer](pcd))
|
||||||
discard wsaCloseEvent(hEvent)
|
discard wsaCloseEvent(hEvent)
|
||||||
raiseOSError(osLastError())
|
raiseOSError(err)
|
||||||
|
|
||||||
pcd.ovl = ol
|
pcd.ovl = ol
|
||||||
if not registerWaitForSingleObject(addr(pcd.waitFd), hEvent,
|
if not registerWaitForSingleObject(addr(pcd.waitFd), hEvent,
|
||||||
cast[WAITORTIMERCALLBACK](waitableCallback),
|
cast[WAITORTIMERCALLBACK](waitableCallback),
|
||||||
cast[pointer](pcd), INFINITE, flags):
|
cast[pointer](pcd), INFINITE, flags):
|
||||||
|
let err = osLastError()
|
||||||
GC_unref(ol)
|
GC_unref(ol)
|
||||||
deallocShared(cast[pointer](pcd))
|
deallocShared(cast[pointer](pcd))
|
||||||
discard wsaCloseEvent(hEvent)
|
discard wsaCloseEvent(hEvent)
|
||||||
raiseOSError(osLastError())
|
raiseOSError(err)
|
||||||
p.handles.incl(fd)
|
p.handles.incl(fd)
|
||||||
|
|
||||||
proc addRead*(fd: AsyncFD, cb: Callback) =
|
proc addRead*(fd: AsyncFD, cb: Callback) =
|
||||||
|
|
@ -963,12 +968,25 @@ when defined(windows) or defined(nimdoc):
|
||||||
if not registerWaitForSingleObject(addr(pcd.waitFd), hEvent,
|
if not registerWaitForSingleObject(addr(pcd.waitFd), hEvent,
|
||||||
cast[WAITORTIMERCALLBACK](waitableCallback),
|
cast[WAITORTIMERCALLBACK](waitableCallback),
|
||||||
cast[pointer](pcd), timeout.Dword, flags):
|
cast[pointer](pcd), timeout.Dword, flags):
|
||||||
|
let err = osLastError()
|
||||||
GC_unref(ol)
|
GC_unref(ol)
|
||||||
deallocShared(cast[pointer](pcd))
|
deallocShared(cast[pointer](pcd))
|
||||||
discard closeHandle(hEvent)
|
discard closeHandle(hEvent)
|
||||||
raiseOSError(osLastError())
|
raiseOSError(err)
|
||||||
p.handles.incl(handleFD)
|
p.handles.incl(handleFD)
|
||||||
|
|
||||||
|
template closeWaitable(handle: untyped) =
|
||||||
|
let waitFd = pcd.waitFd
|
||||||
|
deallocShared(cast[pointer](pcd))
|
||||||
|
p.handles.excl(fd)
|
||||||
|
if unregisterWait(waitFd) == 0:
|
||||||
|
let err = osLastError()
|
||||||
|
if err.int32 != ERROR_IO_PENDING:
|
||||||
|
discard closeHandle(handle)
|
||||||
|
raiseOSError(err)
|
||||||
|
if closeHandle(handle) == 0:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
proc addTimer*(timeout: int, oneshot: bool, cb: Callback) =
|
proc addTimer*(timeout: int, oneshot: bool, cb: Callback) =
|
||||||
## Registers callback ``cb`` to be called when timer expired.
|
## Registers callback ``cb`` to be called when timer expired.
|
||||||
## ``timeout`` - timeout value in milliseconds.
|
## ``timeout`` - timeout value in milliseconds.
|
||||||
|
|
@ -989,13 +1007,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
proc timercb(fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
|
proc timercb(fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
|
||||||
let res = cb(fd)
|
let res = cb(fd)
|
||||||
if res or oneshot:
|
if res or oneshot:
|
||||||
if unregisterWait(pcd.waitFd) == 0:
|
closeWaitable(hEvent)
|
||||||
let err = osLastError()
|
|
||||||
if err.int32 != ERROR_IO_PENDING:
|
|
||||||
raiseOSError(osLastError())
|
|
||||||
discard closeHandle(hEvent)
|
|
||||||
deallocShared(cast[pointer](pcd))
|
|
||||||
p.handles.excl(fd)
|
|
||||||
else:
|
else:
|
||||||
# if callback returned `false`, then it wants to be called again, so
|
# if callback returned `false`, then it wants to be called again, so
|
||||||
# we need to ref and protect `pcd.ovl` again, because it will be
|
# we need to ref and protect `pcd.ovl` again, because it will be
|
||||||
|
|
@ -1018,13 +1030,7 @@ when defined(windows) or defined(nimdoc):
|
||||||
var flags = WT_EXECUTEINWAITTHREAD.Dword
|
var flags = WT_EXECUTEINWAITTHREAD.Dword
|
||||||
|
|
||||||
proc proccb(fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
|
proc proccb(fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
|
||||||
if unregisterWait(pcd.waitFd) == 0:
|
closeWaitable(hProcess)
|
||||||
let err = osLastError()
|
|
||||||
if err.int32 != ERROR_IO_PENDING:
|
|
||||||
raiseOSError(osLastError())
|
|
||||||
discard closeHandle(hProcess)
|
|
||||||
deallocShared(cast[pointer](pcd))
|
|
||||||
p.handles.excl(fd)
|
|
||||||
discard cb(fd)
|
discard cb(fd)
|
||||||
|
|
||||||
registerWaitableHandle(p, hProcess, flags, pcd, INFINITE, proccb)
|
registerWaitableHandle(p, hProcess, flags, pcd, INFINITE, proccb)
|
||||||
|
|
@ -1052,20 +1058,21 @@ when defined(windows) or defined(nimdoc):
|
||||||
## Unregisters event ``ev``.
|
## Unregisters event ``ev``.
|
||||||
if ev.hWaiter != 0:
|
if ev.hWaiter != 0:
|
||||||
let p = getGlobalDispatcher()
|
let p = getGlobalDispatcher()
|
||||||
|
p.handles.excl(AsyncFD(ev.hEvent))
|
||||||
if unregisterWait(ev.hWaiter) == 0:
|
if unregisterWait(ev.hWaiter) == 0:
|
||||||
let err = osLastError()
|
let err = osLastError()
|
||||||
if err.int32 != ERROR_IO_PENDING:
|
if err.int32 != ERROR_IO_PENDING:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(err)
|
||||||
p.handles.excl(AsyncFD(ev.hEvent))
|
|
||||||
ev.hWaiter = 0
|
ev.hWaiter = 0
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError, "Event is not registered!")
|
raise newException(ValueError, "Event is not registered!")
|
||||||
|
|
||||||
proc close*(ev: AsyncEvent) =
|
proc close*(ev: AsyncEvent) =
|
||||||
## Closes event ``ev``.
|
## Closes event ``ev``.
|
||||||
if closeHandle(ev.hEvent) == 0:
|
let res = closeHandle(ev.hEvent)
|
||||||
raiseOSError(osLastError())
|
|
||||||
deallocShared(cast[pointer](ev))
|
deallocShared(cast[pointer](ev))
|
||||||
|
if res == 0:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
proc addEvent*(ev: AsyncEvent, cb: Callback) =
|
proc addEvent*(ev: AsyncEvent, cb: Callback) =
|
||||||
## Registers callback ``cb`` to be called when ``ev`` will be signaled
|
## Registers callback ``cb`` to be called when ``ev`` will be signaled
|
||||||
|
|
@ -1082,8 +1089,8 @@ when defined(windows) or defined(nimdoc):
|
||||||
if cb(fd):
|
if cb(fd):
|
||||||
# we need this check to avoid exception, if `unregister(event)` was
|
# we need this check to avoid exception, if `unregister(event)` was
|
||||||
# called in callback.
|
# called in callback.
|
||||||
if ev.hWaiter != 0: unregister(ev)
|
|
||||||
deallocShared(cast[pointer](pcd))
|
deallocShared(cast[pointer](pcd))
|
||||||
|
if ev.hWaiter != 0: unregister(ev)
|
||||||
else:
|
else:
|
||||||
# if callback returned `false`, then it wants to be called again, so
|
# if callback returned `false`, then it wants to be called again, so
|
||||||
# we need to ref and protect `pcd.ovl` again, because it will be
|
# we need to ref and protect `pcd.ovl` again, because it will be
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue