Comparison

net/server_epoll.lua @ 11920:ff4e34c448a4

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.
author Kim Alvefur <zash@zash.se>
date Thu, 18 Nov 2021 16:21:43 +0100
parent 11858:2bcd84123eba
child 11922:28f5c8061dad
comparison
equal deleted inserted replaced
11919:fae5441fc6cf 11920:ff4e34c448a4
485 end 485 end
486 end 486 end
487 487
488 -- Called when socket is writable 488 -- Called when socket is writable
489 function interface:onwritable() 489 function interface:onwritable()
490 self._writing = true; -- prevent reentrant writes etc
490 self:onconnect(); 491 self:onconnect();
491 if not self.conn then return; end -- could have been closed in onconnect 492 if not self.conn then return; end -- could have been closed in onconnect
492 self:on("predrain"); 493 self:on("predrain");
493 local buffer = self.writebuffer; 494 local buffer = self.writebuffer;
494 local data = buffer or ""; 495 local data = buffer or "";
512 else 513 else
513 self.writebuffer = nil; 514 self.writebuffer = nil;
514 end 515 end
515 self:setwritetimeout(false); 516 self:setwritetimeout(false);
516 self:ondrain(); -- Be aware of writes in ondrain 517 self:ondrain(); -- Be aware of writes in ondrain
518 self._writing = nil;
517 return ok; 519 return ok;
518 elseif partial then 520 elseif partial then
519 self:debug("Sent %d out of %d buffered bytes", partial, #data); 521 self:debug("Sent %d out of %d buffered bytes", partial, #data);
520 if cfg.keep_buffers and type(buffer) == "table" then 522 if cfg.keep_buffers and type(buffer) == "table" then
521 buffer[1] = data:sub(partial+1); 523 buffer[1] = data:sub(partial+1);
526 self.writebuffer = data:sub(partial+1); 528 self.writebuffer = data:sub(partial+1);
527 end 529 end
528 self:set(nil, true); 530 self:set(nil, true);
529 self:setwritetimeout(); 531 self:setwritetimeout();
530 end 532 end
533 self._writing = nil;
531 if err == "wantwrite" or err == "timeout" then 534 if err == "wantwrite" or err == "timeout" then
532 self:set(nil, true); 535 self:set(nil, true);
533 self:setwritetimeout(); 536 self:setwritetimeout();
534 elseif err == "wantread" then 537 elseif err == "wantread" then
535 self:set(true, nil); 538 self:set(true, nil);
555 self:noise("Allocating buffer!") 558 self:noise("Allocating buffer!")
556 self.writebuffer = { buffer, data }; 559 self.writebuffer = { buffer, data };
557 elseif buffer == nil then 560 elseif buffer == nil then
558 self.writebuffer = data; 561 self.writebuffer = data;
559 end 562 end
560 if not self._write_lock then 563 if not self._write_lock and not self._writing then
561 if self._writable and cfg.opportunistic_writes and not self._opportunistic_write then 564 if self._writable and cfg.opportunistic_writes and not self._opportunistic_write then
562 self._opportunistic_write = true; 565 self._opportunistic_write = true;
563 local ret, err = self:onwritable(); 566 local ret, err = self:onwritable();
564 self._opportunistic_write = nil; 567 self._opportunistic_write = nil;
565 return ret, err; 568 return ret, err;