about summary refs log tree commit diff stats
path: root/src/io
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-11-24 20:03:21 +0100
committerbptato <nincsnevem662@gmail.com>2022-11-24 20:03:21 +0100
commit896489a6c500e28f13d0237ab691622cb5c5114f (patch)
tree91b92da01bc126c2489a3dd083df5f9de06927c6 /src/io
parentee930b0f5a587768d340c4204cf1f2e9fb818c89 (diff)
downloadchawan-896489a6c500e28f13d0237ab691622cb5c5114f.tar.gz
Avoid forking child processes from the main process
Caveat: this breaks piped streams.
Diffstat (limited to 'src/io')
-rw-r--r--src/io/loader.nim66
1 files changed, 27 insertions, 39 deletions
diff --git a/src/io/loader.nim b/src/io/loader.nim
index f06ea49a..d189a797 100644
--- a/src/io/loader.nim
+++ b/src/io/loader.nim
@@ -35,11 +35,14 @@ const DefaultHeaders0 = {
   "Pragma": "no-cache",
   "Cache-Control": "no-cache",
 }.toTable()
-let DefaultHeaders = DefaultHeaders0.newHeaderList()
+let DefaultHeaders* = DefaultHeaders0.newHeaderList()
 
-type FileLoader* = ref object
-  defaultHeaders*: HeaderList
-  process*: Pid
+type
+  FileLoader* = object
+    process*: Pid
+
+  LoaderCommand = enum
+    LOAD, QUIT
 
 proc loadFile(url: Url, ostream: Stream) =
   when defined(windows) or defined(OS2) or defined(DOS):
@@ -66,7 +69,7 @@ proc loadFile(url: Url, ostream: Stream) =
         if n < bufferSize:
           break
 
-proc loadResource(loader: FileLoader, request: Request, ostream: Stream) =
+proc loadResource(request: Request, ostream: Stream) =
   case request.url.scheme
   of "file":
     loadFile(request.url, ostream)
@@ -77,10 +80,10 @@ proc loadResource(loader: FileLoader, request: Request, ostream: Stream) =
     ostream.flush()
 
 var ssock: ServerSocket
-proc runFileLoader(loader: FileLoader, fd: cint) =
+proc runFileLoader*(fd: cint, defaultHeaders: HeaderList) =
   if curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK:
     raise newException(Defect, "Failed to initialize libcurl.")
-  ssock = initServerSocket(getpid())
+  ssock = initServerSocket()
   # The server has been initialized, so the main process can resume execution.
   var writef: File
   if not open(writef, FileHandle(fd), fmWrite):
@@ -96,11 +99,18 @@ proc runFileLoader(loader: FileLoader, fd: cint) =
   while true:
     let stream = ssock.acceptSocketStream()
     try:
-      let request = stream.readRequest()
-      for k, v in loader.defaultHeaders.table:
-        if k notin request.headers.table:
-          request.headers.table[k] = v
-      loader.loadResource(request, stream)
+      var cmd: LoaderCommand
+      stream.sread(cmd)
+      case cmd
+      of LOAD:
+        var request: Request
+        stream.read(request)
+        for k, v in defaultHeaders.table:
+          if k notin request.headers.table:
+            request.headers.table[k] = v
+        loadResource(request, stream)
+      of QUIT:
+        break
     except IOError:
       # End-of-file, quit.
       # TODO this should be EOFError
@@ -113,6 +123,7 @@ proc runFileLoader(loader: FileLoader, fd: cint) =
 proc doRequest*(loader: FileLoader, request: Request): Response =
   new(result)
   let stream = connectSocketStream(loader.process)
+  stream.swrite(LOAD)
   stream.swrite(request)
   stream.flush()
   stream.sread(result.res)
@@ -129,30 +140,7 @@ proc doRequest*(loader: FileLoader, request: Request): Response =
     # Only a stream of the response body may arrive after this point.
     result.body = stream
 
-proc newFileLoader*(defaultHeaders: HeaderList): FileLoader =
-  new(result)
-  result.defaultHeaders = defaultHeaders
-  when defined(posix):
-    var pipefd: array[0..1, cint]
-    if pipe(pipefd) == -1:
-      raise newException(Defect, "Failed to open pipe.")
-    let pid = fork()
-    if pid == -1:
-      raise newException(Defect, "Failed to fork network process")
-    elif pid == 0:
-      # child process
-      discard close(pipefd[0]) # close read
-      result.runFileLoader(pipefd[1])
-    else:
-      result.process = pid
-      let readfd = pipefd[0] # get read
-      discard close(pipefd[1]) # close write
-      var readf: File
-      if not open(readf, FileHandle(readfd), fmRead):
-        raise newException(Defect, "Failed to open output handle.")
-      assert readf.readChar() == char(0u8)
-      close(readf)
-      discard close(pipefd[0])
-
-proc newFileLoader*(): FileLoader =
-  newFileLoader(DefaultHeaders)
+proc quit*(loader: FileLoader) =
+  let stream = connectSocketStream(loader.process)
+  if stream != nil:
+    stream.swrite(QUIT)