diff options
author | bptato <nincsnevem662@gmail.com> | 2024-02-29 23:23:40 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-02-29 23:31:38 +0100 |
commit | afafcaf1047f721c8d061d883329d0e556326511 (patch) | |
tree | 2abc62a06227c7aa9c573f9ce52424df638ccba8 /src/local | |
parent | f4b53af1261e6f9be16a315247ace80fcb816505 (diff) | |
download | chawan-afafcaf1047f721c8d061d883329d0e556326511.tar.gz |
buffer, client: fix deadlock with send() calls
This is an ancient bug, but it got much easier to trigger with mouse scrolling support so it's time to fix it. (The bug itself was that since both the client and buffer ends of the controlling stream are blocking, they could get stuck when both were trying to send() data to the other end but the buffer was full. So now we set the client end to non-blocking.)
Diffstat (limited to 'src/local')
-rw-r--r-- | src/local/client.nim | 17 | ||||
-rw-r--r-- | src/local/container.nim | 13 | ||||
-rw-r--r-- | src/local/pager.nim | 6 |
3 files changed, 26 insertions, 10 deletions
diff --git a/src/local/client.nim b/src/local/client.nim index 76a61bfa..3a80b4bf 100644 --- a/src/local/client.nim +++ b/src/local/client.nim @@ -21,6 +21,7 @@ import display/term import html/chadombuilder import html/dom import html/event +import io/bufstream import io/posixstream import io/promise import io/socketstream @@ -41,6 +42,7 @@ import loader/loader import loader/request import local/container import local/pager +import server/buffer import server/forkserver import types/blob import types/cookie @@ -450,12 +452,15 @@ proc acceptBuffers(client: Client) = client.pager.procmap.del(pid) stream.close() var accepted: seq[Pid] + let registerFun = proc(fd: int) = + client.selector.unregister(fd) + client.selector.registerHandle(fd, {Read, Write}, 0) for pid, container in client.pager.procmap: let stream = connectSocketStream(pid, buffered = false, blocking = true) if stream == nil: client.pager.alert("Error: failed to set up buffer") continue - container.setStream(stream) + container.setStream(stream, registerFun) let fd = int(stream.fd) client.fdmap[fd] = container client.selector.registerHandle(fd, {Read}, 0) @@ -513,6 +518,12 @@ proc handleRead(client: Client, fd: int) = let container = client.fdmap[fd] client.pager.handleEvent(container) +proc handleWrite(client: Client, fd: int) = + let container = client.fdmap[fd] + if container.iface.stream.flushWrite(): + client.selector.unregister(fd) + client.selector.registerHandle(fd, {Read}, 0) + proc flushConsole*(client: Client) {.jsfunc.} = if client.console == nil: # hack for when client crashes before console has been initialized @@ -561,6 +572,8 @@ proc inputLoop(client: Client) = for event in events: if Read in event.events: client.handleRead(event.fd) + if Write in event.events: + client.handleWrite(event.fd) if Error in event.events: client.handleError(event.fd) if Signal in event.events: @@ -597,6 +610,8 @@ proc headlessLoop(client: Client) = for event in events: if Read in event.events: client.handleRead(event.fd) + if Write in event.events: + client.handleWrite(event.fd) if Error in event.events: client.handleError(event.fd) if selectors.Event.Timer in event.events: diff --git a/src/local/container.nim b/src/local/container.nim index 03cad675..5d5e6669 100644 --- a/src/local/container.nim +++ b/src/local/container.nim @@ -1,6 +1,5 @@ import std/deques import std/options -import std/streams import std/unicode when defined(posix): @@ -11,6 +10,7 @@ import display/term import extern/stdio import io/promise import io/serialize +import io/socketstream import js/javascript import js/jstypes import js/regex @@ -144,8 +144,8 @@ jsDestructor(Highlight) jsDestructor(Container) proc newBuffer*(forkserver: ForkServer, config: BufferConfig, - request: Request, attrs: WindowAttributes, title = "", - redirectdepth = 0, canreinterpret = true, fd = FileHandle(-1), + request: Request, attrs: WindowAttributes, title: string, + redirectdepth: int, canreinterpret: bool, fd: FileHandle, contentType: Option[string]): Container = let (process, loaderPid) = forkserver.forkBuffer(request, config, attrs) if fd != -1: @@ -1575,12 +1575,13 @@ proc handleCommand(container: Container) = container.iface.stream.sread(packetid) container.iface.resolve(packetid, len - slen(packetid)) -proc setStream*(container: Container, stream: Stream) = +proc setStream*(container: Container, stream: SocketStream, + registerFun: proc(fd: int)) = if not container.cloned: - container.iface = newBufferInterface(stream) + container.iface = newBufferInterface(stream, registerFun) container.load() else: - container.iface = cloneInterface(stream) + container.iface = cloneInterface(stream, registerFun) # Maybe we have to resume loading. Let's try. discard container.iface.load().then(proc(res: int) = container.onload(res) diff --git a/src/local/pager.nim b/src/local/pager.nim index 1040c259..d8f7c5dd 100644 --- a/src/local/pager.nim +++ b/src/local/pager.nim @@ -21,8 +21,8 @@ import extern/editor import extern/runproc import extern/stdio import extern/tempfile +import io/posixstream import io/promise -import io/socketstream import js/error import js/javascript import js/jstypes @@ -86,7 +86,7 @@ type statusgrid*: FixedGrid term*: Terminal tmpdir: string - unreg*: seq[(Pid, SocketStream)] + unreg*: seq[(Pid, PosixStream)] urimethodmap: URIMethodMap username: string @@ -583,7 +583,7 @@ proc deleteContainer(pager: Pager, container: Container) = pager.setContainer(nil) container.parent = nil container.children.setLen(0) - pager.unreg.add((container.process, SocketStream(container.iface.stream))) + pager.unreg.add((container.process, container.iface.stream)) pager.forkserver.removeChild(container.process) proc discardBuffer(pager: Pager, container = none(Container)) {.jsfunc.} = |