diff options
author | bptato <nincsnevem662@gmail.com> | 2024-09-03 00:07:40 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-09-03 00:15:20 +0200 |
commit | 6d8c2fca2e39cc9f3cc9a99cac5584864eaa0ed4 (patch) | |
tree | 72a4dad7bec3afa433574df7b3413b0177d21aea /src/loader | |
parent | 6ecac397b43de14589c29b601fd9e4d8b8524d9a (diff) | |
download | chawan-6d8c2fca2e39cc9f3cc9a99cac5584864eaa0ed4.tar.gz |
loader: fix crashes with kqueue backend
pain... (also, fix an fd leak, plus a more general bug where we registered empty output handles.)
Diffstat (limited to 'src/loader')
-rw-r--r-- | src/loader/loader.nim | 25 | ||||
-rw-r--r-- | src/loader/loaderhandle.nim | 2 |
2 files changed, 23 insertions, 4 deletions
diff --git a/src/loader/loader.nim b/src/loader/loader.nim index 01593a00..b655b917 100644 --- a/src/loader/loader.nim +++ b/src/loader/loader.nim @@ -196,9 +196,27 @@ proc register(ctx: LoaderContext; output: OutputHandle) = ctx.selector.registerHandle(int(output.ostream.fd), {Write}, 0) output.registered = true +const bsdPlatform = defined(macosx) or defined(freebsd) or defined(netbsd) or + defined(openbsd) or defined(dragonfly) proc unregister(ctx: LoaderContext; output: OutputHandle) = assert output.registered - ctx.selector.unregister(int(output.ostream.fd)) + # so kqueue-based selectors raise when we try to unregister a pipe whose + # reader is at EOF. "solution": clean up this mess ourselves. + let fd = int(output.ostream.fd) + when bsdPlatform: + let oc = ctx.selector.count + try: + ctx.selector.unregister(fd) + except IOSelectorsException: + # ???? + for name, f in ctx.selector[].fieldPairs: + when name == "fds": + cast[ptr int](addr f[fd])[] = -1 + elif name == "changes": + f.setLen(0) + ctx.selector.count = oc - 1 + else: + ctx.selector.unregister(int(output.ostream.fd)) output.registered = false # Either write data to the target output, or append it to the list of buffers to @@ -405,6 +423,7 @@ proc loadFromCache(ctx: LoaderContext; client: ClientData; handle: LoaderHandle; let ps = newPosixStream(client.cacheMap[n].path, O_RDONLY, 0) if startFrom != 0: ps.seek(startFrom) + handle.istream = ps if ps == nil: handle.rejectHandle(ERROR_FILE_NOT_IN_CACHE) client.cacheMap.del(n) @@ -412,7 +431,6 @@ proc loadFromCache(ctx: LoaderContext; client: ClientData; handle: LoaderHandle; handle.sendResult(0) handle.sendStatus(200) handle.sendHeaders(newHeaders()) - handle.istream = ps handle.output.ostream.setBlocking(false) let cachedHandle = ctx.findCachedHandle(id) ctx.loadStreamRegular(handle, cachedHandle) @@ -497,7 +515,8 @@ proc loadResource(ctx: LoaderContext; client: ClientData; let output = outputIn.tee(ostream, ctx.getOutputId(), client.pid) ctx.outputMap[ostream.fd] = output output.suspended = false - ctx.register(output) + if not output.isEmpty: + ctx.register(output) else: ostream.sclose() ctx.addFd(handle) diff --git a/src/loader/loaderhandle.nim b/src/loader/loaderhandle.nim index 7637bdac..156bd22c 100644 --- a/src/loader/loaderhandle.nim +++ b/src/loader/loaderhandle.nim @@ -195,12 +195,12 @@ proc iclose*(handle: LoaderHandle) = handle.istream = nil proc oclose*(output: OutputHandle) = + assert not output.registered output.ostream.sclose() output.ostream = nil proc close*(handle: LoaderHandle) = handle.iclose() for output in handle.outputs: - assert not output.registered if output.ostream != nil: output.oclose() |