Mercurial > prosody-hg
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 |
| parents | 2bcd84123eba |
| children | 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; |
