Software /
code /
prosody
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; |