summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorDominik Picheta <dominikpicheta@googlemail.com>2016-09-02 18:21:35 +0200
committerGitHub <noreply@github.com>2016-09-02 18:21:35 +0200
commit46948a9509d77e025b33e4f890bf510b4eec9d46 (patch)
treeec7e4e4b54bd67fdfb5715818da854cef6a91d01
parenta5de03ea25712a2e948de09b32032f4632aa3bbd (diff)
parentc5ffdd03897225ebcb8bef23bdb64f212c45e8e8 (diff)
downloadNim-46948a9509d77e025b33e4f890bf510b4eec9d46.tar.gz
Merge pull request #4680 from cheatfate/asyncwinsend
async: protect data argument in windows send operation.
-rw-r--r--lib/pure/asyncdispatch.nim7
-rw-r--r--lib/upcoming/asyncdispatch.nim7
2 files changed, 12 insertions, 2 deletions
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index 79bc1b96d..cefa233be 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -827,14 +827,17 @@ when defined(windows) or defined(nimdoc):
     var retFuture = newFuture[void]("send")
 
     var dataBuf: TWSABuf
-    dataBuf.buf = data # since this is not used in a callback, this is fine
+    dataBuf.buf = data
     dataBuf.len = data.len.ULONG
+    GC_ref(data) # we need to protect data until send operation is completed
+                 # or failed.
 
     var bytesReceived, lowFlags: Dword
     var ol = PCustomOverlapped()
     GC_ref(ol)
     ol.data = CompletionData(fd: socket, cb:
       proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
+        GC_unref(data) # if operation completed `data` must be released.
         if not retFuture.finished:
           if errcode == OSErrorCode(-1):
             retFuture.complete()
@@ -851,6 +854,8 @@ when defined(windows) or defined(nimdoc):
       let err = osLastError()
       if err.int32 != ERROR_IO_PENDING:
         GC_unref(ol)
+        GC_unref(data) # if operation failed `data` must be released, because
+                       # completion routine will not be called.
         if flags.isDisconnectionError(err):
           retFuture.complete()
         else:
diff --git a/lib/upcoming/asyncdispatch.nim b/lib/upcoming/asyncdispatch.nim
index 19c9815d2..4a079e895 100644
--- a/lib/upcoming/asyncdispatch.nim
+++ b/lib/upcoming/asyncdispatch.nim
@@ -796,14 +796,17 @@ when defined(windows) or defined(nimdoc):
     var retFuture = newFuture[void]("send")
 
     var dataBuf: TWSABuf
-    dataBuf.buf = data # since this is not used in a callback, this is fine
+    dataBuf.buf = data
     dataBuf.len = data.len.ULONG
+    GC_ref(data) # we need to protect data until send operation is completed
+                 # or failed.
 
     var bytesReceived, lowFlags: Dword
     var ol = PCustomOverlapped()
     GC_ref(ol)
     ol.data = CompletionData(fd: socket, cb:
       proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
+        GC_unref(data) # if operation completed `data` must be released.
         if not retFuture.finished:
           if errcode == OSErrorCode(-1):
             retFuture.complete()
@@ -820,6 +823,8 @@ when defined(windows) or defined(nimdoc):
       let err = osLastError()
       if err.int32 != ERROR_IO_PENDING:
         GC_unref(ol)
+        GC_unref(data) # if operation failed `data` must be released, because
+                       # completion routine will not be called.
         if flags.isDisconnectionError(err):
           retFuture.complete()
         else: