about summary refs log tree commit diff stats
path: root/src/local
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-06-21 20:13:21 +0200
committerbptato <nincsnevem662@gmail.com>2024-06-21 20:32:09 +0200
commit7ffce10055c6b553781e0b747506f6a3a50718a6 (patch)
tree56f2646592640e6feecd5590289e3c2d811550ad /src/local
parent51ae4cc4ec4402f78bbda6de5207c60b6a1aaf86 (diff)
downloadchawan-7ffce10055c6b553781e0b747506f6a3a50718a6.tar.gz
client, pager: fix cached item refcounting bugs
Diffstat (limited to 'src/local')
-rw-r--r--src/local/client.nim18
-rw-r--r--src/local/container.nim4
-rw-r--r--src/local/pager.nim22
3 files changed, 30 insertions, 14 deletions
diff --git a/src/local/client.nim b/src/local/client.nim
index ee469652..c52ea71f 100644
--- a/src/local/client.nim
+++ b/src/local/client.nim
@@ -426,21 +426,25 @@ proc acceptBuffers(client: Client) =
       pager.alert("Error: failed to set up buffer")
       continue
     let key = pager.addLoaderClient(container.process, container.loaderConfig)
+    let loader = pager.loader
     stream.withPacketWriter w:
       w.swrite(key)
-      let loader = pager.loader
       if item.fdin != -1:
         let outputId = item.istreamOutputId
         if container.cacheId == -1:
-          (container.cacheId, container.cacheFile) =
-            loader.addCacheFile(outputId, loader.clientPid)
+          container.cacheId = loader.addCacheFile(outputId, loader.clientPid)
+        if container.request.url.scheme == "cache":
+          # loading from cache; now both the buffer and us hold a new reference
+          # to the cached item, but it's only shared with the buffer. add a
+          # pager ref too.
+          loader.shareCachedItem(container.cacheId, loader.clientPid)
         var outCacheId = container.cacheId
         let pid = container.process
         if item.fdout == item.fdin:
           loader.shareCachedItem(container.cacheId, pid)
           loader.resume(item.istreamOutputId)
         else:
-          outCacheId = loader.addCacheFile(item.ostreamOutputId, pid).outputId
+          outCacheId = loader.addCacheFile(item.ostreamOutputId, pid)
           loader.resume([item.istreamOutputId, item.ostreamOutputId])
         w.swrite(outCacheId)
     if item.fdin != -1:
@@ -450,7 +454,11 @@ proc acceptBuffers(client: Client) =
       discard close(item.fdout)
       container.setStream(stream, registerFun)
     else:
-      # buffer is cloned, no need to cache anything
+      # buffer is cloned, just share the parent's cached source
+      loader.shareCachedItem(container.cacheId, container.process)
+      # also add a reference here; it will be removed when the container is
+      # deleted
+      loader.shareCachedItem(container.cacheId, loader.clientPid)
       container.setCloneStream(stream, registerFun)
     let fd = int(stream.fd)
     client.fdmap[fd] = container
diff --git a/src/local/container.nim b/src/local/container.nim
index 8717610f..7aa5d324 100644
--- a/src/local/container.nim
+++ b/src/local/container.nim
@@ -154,7 +154,6 @@ type
     filter*: BufferFilter
     bgcolor*: CellColor
     tailOnLoad*: bool
-    cacheFile* {.jsget.}: string
     mainConfig*: Config
     flags*: set[ContainerFlag]
     images*: seq[PosBitmap]
@@ -168,7 +167,7 @@ proc newContainer*(config: BufferConfig; loaderConfig: LoaderClientConfig;
     url: URL; request: Request; luctx: LUContext; attrs: WindowAttributes;
     title: string; redirectDepth: int; flags: set[ContainerFlag];
     contentType: Option[string]; charsetStack: seq[Charset]; cacheId: int;
-    cacheFile: string; mainConfig: Config): Container =
+    mainConfig: Config): Container =
   return Container(
     url: url,
     request: request,
@@ -184,7 +183,6 @@ proc newContainer*(config: BufferConfig; loaderConfig: LoaderClientConfig;
     ),
     loadinfo: "Connecting to " & request.url.host & "...",
     cacheId: cacheId,
-    cacheFile: cacheFile,
     process: -1,
     mainConfig: mainConfig,
     flags: flags,
diff --git a/src/local/pager.nim b/src/local/pager.nim
index 8760da86..a70b2b3d 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -483,7 +483,7 @@ proc draw*(pager: Pager) =
         let bmp = NetworkBitmap(image.bmp)
         let cached = container.findCachedImage(bmp.imageId)
         if cached == nil:
-          let (cacheId, _) = pager.loader.addCacheFile(bmp.outputId,
+          let cacheId = pager.loader.addCacheFile(bmp.outputId,
             pager.loader.clientPid, container.process)
           let request = newRequest(newURL("cache:" & $cacheId).get)
           # capture bmp for the closure
@@ -566,9 +566,13 @@ proc newContainer(pager: Pager; bufferConfig: BufferConfig;
     loaderConfig: LoaderClientConfig; request: Request; title = "";
     redirectDepth = 0; flags = {cfCanReinterpret, cfUserRequested};
     contentType = none(string); charsetStack: seq[Charset] = @[];
-    url = request.url; cacheId = -1; cacheFile = ""): Container =
+    url = request.url): Container =
   let stream = pager.loader.startRequest(request, loaderConfig)
   pager.loader.registerFun(stream.fd)
+  let cacheId = if request.url.scheme == "cache":
+    parseInt32(request.url.pathname).get(-1)
+  else:
+    -1
   let container = newContainer(
     bufferConfig,
     loaderConfig,
@@ -582,7 +586,6 @@ proc newContainer(pager: Pager; bufferConfig: BufferConfig;
     contentType,
     charsetStack,
     cacheId,
-    cacheFile,
     pager.config
   )
   pager.connectingContainers.add(ConnectingContainerItem(
@@ -602,9 +605,7 @@ proc newContainerFrom(pager: Pager; container: Container; contentType: string):
     newRequest(url),
     contentType = some(contentType),
     charsetStack = container.charsetStack,
-    url = container.url,
-    cacheId = container.cacheId,
-    cacheFile = container.cacheFile
+    url = container.url
   )
 
 func findConnectingContainer*(pager: Pager; fd: int): int =
@@ -835,6 +836,7 @@ proc deleteContainer(pager: Pager; container, setTarget: Container) =
     pager.setContainer(setTarget)
   pager.unreg.add(container)
   if container.process != -1:
+    pager.loader.removeCachedItem(container.cacheId)
     pager.forkserver.removeChild(container.process)
     pager.loader.removeClient(container.process)
 
@@ -927,6 +929,14 @@ proc toggleSource(pager: Pager) {.jsfunc.} =
       pager.container.sourcepair = container
       pager.addContainer(container)
 
+proc getCacheFile(pager: Pager; cacheId: int): string {.jsfunc.} =
+  return pager.loader.getCacheFile(cacheId)
+
+proc cacheFile(pager: Pager): string {.jsfget.} =
+  if pager.container != nil:
+    return pager.getCacheFile(pager.container.cacheId)
+  return ""
+
 proc getEditorCommand(pager: Pager; file: string; line = 1): string {.jsfunc.} =
   var editor = pager.config.external.editor
   if (let uqEditor = ChaPath(editor).unquote(); uqEditor.isSome):