Index: trunk/src/VBox/Devices/Network/slirp/slirp.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 41165)
+++ trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 41178)
@@ -267,4 +267,24 @@
     0x0, 0x0, 0x0, 0x0, 0x0, 0x0
 };
+
+/**
+ * This helper routine do the checks in descriptions to
+ * ''fUnderPolling'' and ''fShouldBeRemoved'' flags
+ * @returns 1 if socket removed and 0 if no changes was made.
+ */
+static int slirpVerifyAndFreeSocket(PNATState pData, struct socket *pSocket)
+{
+    AssertPtrReturn(pData, 0);
+    AssertPtrReturn(pSocket, 0);
+    AssertReturn(pSocket->fUnderPolling, 0);
+    if (pSocket->fShouldBeRemoved)
+    {
+        pSocket->fUnderPolling = 0;
+        sofree(pData, pSocket);
+        /* so is PHANTOM, now */
+        return 1;
+    }
+    return 0;
+}
 
 #ifdef RT_OS_WINDOWS
@@ -1238,4 +1258,6 @@
             CONTINUE(tcp);
 
+        Assert(!so->fUnderPolling);
+        so->fUnderPolling = 1;
         POLL_TCP_EVENTS(rc, error, so, &NetworkEvents);
 
@@ -1266,4 +1288,6 @@
         {
             sorecvoob(pData, so);
+            if (slirpVerifyAndFreeSocket(pData, so))
+                CONTINUE(tcp);
         }
 
@@ -1282,4 +1306,6 @@
                 bool fRet = slirpConnectOrWrite(pData, so, true);
                 LogFunc(("fRet:%RTbool\n", fRet));
+                if (slirpVerifyAndFreeSocket(pData, so))
+                    CONTINUE(tcp);
             }
 #endif
@@ -1290,12 +1316,22 @@
             {
                 TCP_CONNECT(pData, so);
+                if (slirpVerifyAndFreeSocket(pData, so))
+                    CONTINUE(tcp);
                 if (!CHECK_FD_SET(so, NetworkEvents, closefds))
+                {
+                    so->fUnderPolling = 0;
                     CONTINUE(tcp);
+                }
             }
 
             ret = soread(pData, so);
+            if (slirpVerifyAndFreeSocket(pData, so))
+                CONTINUE(tcp);
             /* Output it if we read something */
             if (RT_LIKELY(ret > 0))
                 TCP_OUTPUT(pData, sototcpcb(so));
+
+            if (slirpVerifyAndFreeSocket(pData, so))
+                CONTINUE(tcp);
         }
 
@@ -1307,20 +1343,17 @@
             || (so->so_close == 1))
         {
-            struct socket *pPrevSo = NULL;
-            /**
-             * we need easy way to detection mechanism if socket has been freed or not
-             * before continuing any further diagnostic.
-             */
-            pPrevSo = so->so_prev;
-            AssertPtr(pPrevSo);
             /*
              * drain the socket
              */
-            for (; pPrevSo->so_next == so ;)
+            for (;   so_next->so_prev == so
+                  && !slirpVerifyAndFreeSocket(pData, so);)
             {
                 ret = soread(pData, so);
+                if (slirpVerifyAndFreeSocket(pData, so))
+                    break;
+
                 if (ret > 0)
                     TCP_OUTPUT(pData, sototcpcb(so));
-                else if (pPrevSo->so_next == so)
+                else if (so_next->so_prev == so)
                 {
                     Log2(("%R[natsock] errno %d (%s)\n", so, errno, strerror(errno)));
@@ -1328,5 +1361,7 @@
                 }
             }
-            if (pPrevSo->so_next == so)
+
+            /* if socket freed ''so'' is PHANTOM and next socket isn't points on it */
+            if (so_next->so_prev == so)
             {
                 /* mark the socket for termination _after_ it was drained */
@@ -1339,4 +1374,6 @@
 #endif
             }
+            if (so_next->so_prev == so)
+                so->fUnderPolling = 0;
             CONTINUE(tcp);
         }
@@ -1352,5 +1389,9 @@
         {
             if(!slirpConnectOrWrite(pData, so, false))
+            {
+                if (!slirpVerifyAndFreeSocket(pData, so))
+                    so->fUnderPolling = 0;
                 CONTINUE(tcp);
+            }
         }
 
@@ -1403,4 +1444,6 @@
         } /* SS_ISFCONNECTING */
 #endif
+        if (!slirpVerifyAndFreeSocket(pData, so))
+            so->fUnderPolling = 0;
         LOOP_LABEL(tcp, so, so_next);
     }
Index: trunk/src/VBox/Devices/Network/slirp/socket.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/socket.c	(revision 41165)
+++ trunk/src/VBox/Devices/Network/slirp/socket.c	(revision 41178)
@@ -195,11 +195,20 @@
         m_freem(pData, so->so_m);
 #ifndef VBOX_WITH_SLIRP_MT
-    if (so->so_next && so->so_prev)
-    {
-        remque(pData, so);  /* crashes if so is not in a queue */
-        NSOCK_DEC();
-    }
-
-    RTMemFree(so);
+    /*
+     * We should not remove socket when polling routine do the polling
+     * instead we mark it for deletion.
+     */
+    if (!so->fUnderPolling)
+    {
+        if (so->so_next && so->so_prev)
+        {
+            remque(pData, so);  /* crashes if so is not in a queue */
+            NSOCK_DEC();
+        }
+
+        RTMemFree(so);
+    }
+    else
+        so->fShouldBeRemoved = 1;
 #else
     so->so_deleted = 1;
Index: trunk/src/VBox/Devices/Network/slirp/socket.h
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/socket.h	(revision 41165)
+++ trunk/src/VBox/Devices/Network/slirp/socket.h	(revision 41178)
@@ -112,4 +112,26 @@
     int so_cCloneCounter;      /* number of clones */
 #endif
+    /** These flags (''fUnderPolling'' and ''fShouldBeRemoved'') introduced to
+     *  to let polling routine gain control over freeing socket whatever level of
+     *  TCP/IP initiated socket releasing.
+     *  So polling routine when start processing socket alter it's state to
+     *  ''fUnderPolling'' to 1, and clean (set to 0) when it finish.
+     *  When polling routine calls functions it should be ensure on return,
+     *  whether ''fShouldBeRemoved'' set or not, and depending on state call
+     *  ''sofree'' or continue socket processing.
+     *  On ''fShouldBeRemoved'' equal to 1, polling routine should call ''sofree'',
+     *  clearing ''fUnderPolling'' to do real freeng of the socket and removing from
+     *  the queue.
+     *  @todo: perhaps, to simplefy the things we need some helper function.
+     *  @note: it's used like a bool, I use 'int' to avoid compiler warnings
+     *  appearing if [-Wc++-compat] used.
+     */
+    int fUnderPolling;
+    /** This flag used by ''sofree'' function in following manner
+     *
+     *  fUnderPolling = 1, then we don't remove socket from the queue, just
+     *  alter value ''fShouldBeRemoved'' to 1, else we do removal.
+     */
+    int fShouldBeRemoved;
 };
 
