From 858deaf7c064cb2bc839f48c5f7eca35880019db Mon Sep 17 00:00:00 2001
From: Alexandr <a.lyapunov@corp.mail.ru>
Date: Wed, 5 Feb 2014 20:02:02 +0400
Subject: [PATCH] fixed GH-183
 https://github.com/tarantool/tarantool/issues/183

---
 src/coio.cc            | 53 ++++++++++++++++++++++++------------------
 test/box/socket.result | 18 +++++++++++++-
 test/box/socket.test   | 31 +++++++++++++++++++++++-
 3 files changed, 77 insertions(+), 25 deletions(-)

diff --git a/src/coio.cc b/src/coio.cc
index 3d143d9a2f..eea2b53d25 100644
--- a/src/coio.cc
+++ b/src/coio.cc
@@ -172,30 +172,37 @@ coio_accept(struct ev_io *coio, struct sockaddr_in *addr,
 {
 	ev_tstamp start, delay;
 	evio_timeout_init(&start, &delay, timeout);
-	while (true) {
-		/* Assume that there are waiting clients
-		 * available */
-		int fd = sio_accept(coio->fd, addr, &addrlen);
-		if (fd >= 0) {
-			evio_setsockopt_tcp(fd);
-			return fd;
-		}
-		/* The socket is not ready, yield */
-		if (! ev_is_active(coio)) {
-			ev_io_set(coio, coio->fd, EV_READ);
-			ev_io_start(coio);
-		}
-		/*
-		 * Yield control to other fibers until the
-		 * timeout is reached.
-		 */
-		bool is_timedout = coio_fiber_yield_timeout(coio, delay);
-		fiber_testcancel();
-		if (is_timedout) {
-			errno = ETIMEDOUT;
-			tnt_raise(SocketError, coio->fd, "accept");
+
+	{
+		auto scoped_guard = make_scoped_guard([=] {
+				ev_io_stop(coio);
+		});
+
+		while (true) {
+			/* Assume that there are waiting clients
+			 * available */
+			int fd = sio_accept(coio->fd, addr, &addrlen);
+			if (fd >= 0) {
+				evio_setsockopt_tcp(fd);
+				return fd;
+			}
+			/* The socket is not ready, yield */
+			if (! ev_is_active(coio)) {
+				ev_io_set(coio, coio->fd, EV_READ);
+				ev_io_start(coio);
+			}
+			/*
+			 * Yield control to other fibers until the
+			 * timeout is reached.
+			 */
+			bool is_timedout = coio_fiber_yield_timeout(coio, delay);
+			fiber_testcancel();
+			if (is_timedout) {
+				errno = ETIMEDOUT;
+				tnt_raise(SocketError, coio->fd, "accept");
+			}
+			evio_timeout_update(start, &delay);
 		}
-		evio_timeout_update(start, &delay);
 	}
 }
 
diff --git a/test/box/socket.result b/test/box/socket.result
index 9fe4147b6e..0d01a4bfbb 100644
--- a/test/box/socket.result
+++ b/test/box/socket.result
@@ -933,9 +933,25 @@ lua reps
 ---
  - 3
 ...
-lua  function server() 	ms = box.socket.tcp() 	ms:bind('127.0.0.1', 8181) 	ms:listen()  	while true do 		local s = ms:accept( .5 ) 		if s ~= 'timeout' then 			print("accepted connection ", s) 			s:send('Hello world') 			s:shutdown(box.socket.SHUT_RDWR) 		end 	end end  box.fiber.wrap(server) 
+lua  function server() 	ms = box.socket.tcp() 	ms:bind('127.0.0.1', 8181) 	ms:listen()  	while true do 		local s = ms:accept( .5 ) 		if s ~= 'timeout' then 			print("accepted connection ", s) 			s:send('Hello world') 			s:shutdown(box.socket.SHUT_RDWR) 		end 	end end  fbr = box.fiber.wrap(server) 
 ---
 ...
 Hello world
 Hello world
 Hello world
+lua box.fiber.cancel(fbr)
+---
+...
+lua ms:close()
+---
+...
+lua  a = '127.0.0.1' p = 12345 function srv() 	ms = box.socket.tcp() 	ms:bind(a, p) 	ms:listen() 	ms:accept() end  fbr = box.fiber.wrap(srv)  box.socket.tcp():connect(a, p) box.socket.tcp():connect(a, p) 
+---
+...
+lua box.fiber.cancel(fbr)
+---
+error: 'fiber.resume(): the fiber is dead'
+...
+lua ms:close()
+---
+...
diff --git a/test/box/socket.test b/test/box/socket.test
index d544fc117e..93d84681ca 100644
--- a/test/box/socket.test
+++ b/test/box/socket.test
@@ -580,7 +580,7 @@ function server()
 	end
 end
 
-box.fiber.wrap(server)
+fbr = box.fiber.wrap(server)
 """
 
 exec admin "lua " + test.replace('\n', ' ')
@@ -602,3 +602,32 @@ s.connect(('127.0.0.1', 8181))
 data = s.recv(1024)
 s.close()
 print data
+
+#cleanup
+exec admin "lua box.fiber.cancel(fbr)"
+exec admin "lua ms:close()"
+
+
+# GH-183 bug test. Tarantool must not crash after the code below:
+test="""
+a = '127.0.0.1'
+p = 12345
+function srv()
+	ms = box.socket.tcp()
+	ms:bind(a, p)
+	ms:listen()
+	ms:accept()
+end
+
+fbr = box.fiber.wrap(srv)
+
+box.socket.tcp():connect(a, p)
+box.socket.tcp():connect(a, p)
+"""
+
+exec admin "lua " + test.replace('\n', ' ')
+
+#cleanup
+exec admin "lua box.fiber.cancel(fbr)"
+exec admin "lua ms:close()"
+
-- 
GitLab