From 4704104049dfe65b851ec3e434b76907400e9fe3 Mon Sep 17 00:00:00 2001
From: Kim Alvefur <zash@zash.se>
Date: Thu, 18 Nov 2021 16:21:43 +0100
Subject: net.server_epoll: Try harder to avoid reentrant opportunistic writes

Opportunistic writes sure do complicate things. This is especially
intended to avoid opportunistic_writes from within the onpredrain
callback.
---
 net/server_epoll.lua | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/server_epoll.lua b/net/server_epoll.lua
index 0a0f89c5..8a70e2dc 100644
--- a/net/server_epoll.lua
+++ b/net/server_epoll.lua
@@ -487,6 +487,7 @@ end
 
 -- Called when socket is writable
 function interface:onwritable()
+	self._writing = true; -- prevent reentrant writes etc
 	self:onconnect();
 	if not self.conn then return; end -- could have been closed in onconnect
 	self:on("predrain");
@@ -514,6 +515,7 @@ function interface:onwritable()
 		end
 		self:setwritetimeout(false);
 		self:ondrain(); -- Be aware of writes in ondrain
+		self._writing = nil;
 		return ok;
 	elseif partial then
 		self:debug("Sent %d out of %d buffered bytes", partial, #data);
@@ -528,6 +530,7 @@ function interface:onwritable()
 		self:set(nil, true);
 		self:setwritetimeout();
 	end
+	self._writing = nil;
 	if err == "wantwrite" or err == "timeout" then
 		self:set(nil, true);
 		self:setwritetimeout();
@@ -557,7 +560,7 @@ function interface:write(data)
 	elseif buffer == nil then
 		self.writebuffer = data;
 	end
-	if not self._write_lock then
+	if not self._write_lock and not self._writing then
 		if self._writable and cfg.opportunistic_writes and not self._opportunistic_write then
 			self._opportunistic_write = true;
 			local ret, err = self:onwritable();
-- 
cgit v1.2.3