diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 370a774f..8d624e52 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -4014,7 +4014,7 @@ "handler not supported for :datagram servers") (def s (net/listen host port type no-reuse)) (if handler - (ev/go (fn [] (net/accept-loop s handler)))) + (ev/go (fn :net/server-handler [] (net/accept-loop s handler)))) s)) ### @@ -4670,8 +4670,7 @@ (defn- run-main [env subargs arg] - (when-let [entry (in env 'main) - main (or (get entry :value) (in (get entry :ref) 0))] + (when-let [main (module/value env 'main)] (def guard (if (get env :debug) :ydt :y)) (defn wrap-main [&] (main ;subargs)) diff --git a/src/core/io.c b/src/core/io.c index 43996526..274f9eeb 100644 --- a/src/core/io.c +++ b/src/core/io.c @@ -109,10 +109,11 @@ static int32_t checkflags(const uint8_t *str) { return flags; } -static void *makef(FILE *f, int32_t flags) { +static void *makef(FILE *f, int32_t flags, size_t bufsize) { JanetFile *iof = (JanetFile *) janet_abstract(&janet_file_type, sizeof(JanetFile)); iof->file = f; iof->flags = flags; + iof->vbufsize = bufsize; #if !(defined(JANET_WINDOWS) || defined(JANET_PLAN9)) /* While we would like fopen to set cloexec by default (like O_CLOEXEC) with the e flag, that is * not standard. */ @@ -164,6 +165,7 @@ JANET_CORE_FN(cfun_io_fopen, flags = JANET_FILE_READ; } FILE *f = fopen((const char *)fname, (const char *)fmode); + size_t bufsize = BUFSIZ; if (f != NULL) { #if !(defined(JANET_WINDOWS) || defined(JANET_PLAN9)) struct stat st; @@ -173,7 +175,7 @@ JANET_CORE_FN(cfun_io_fopen, janet_panicf("cannot open directory: %s", fname); } #endif - size_t bufsize = janet_optsize(argv, argc, 2, BUFSIZ); + bufsize = janet_optsize(argv, argc, 2, BUFSIZ); if (bufsize != BUFSIZ) { int result = setvbuf(f, NULL, bufsize ? _IOFBF : _IONBF, bufsize); if (result) { @@ -181,7 +183,7 @@ JANET_CORE_FN(cfun_io_fopen, } } } - return f ? janet_makefile(f, flags) + return f ? janet_wrap_abstract(makef(f, flags, bufsize)) : (flags & JANET_FILE_NONIL) ? (janet_panicf("failed to open file %s: %s", fname, janet_strerror(errno)), janet_wrap_nil()) : janet_wrap_nil(); } @@ -410,12 +412,23 @@ static void io_file_marshal(void *p, JanetMarshalContext *ctx) { JanetFile *iof = (JanetFile *)p; if (ctx->flags & JANET_MARSHAL_UNSAFE) { janet_marshal_abstract(ctx, p); + int fno = -1; #ifdef JANET_WINDOWS - janet_marshal_int(ctx, _fileno(iof->file)); + if (iof->flags & JANET_FILE_NOT_CLOSEABLE) { + fno = _fileno(iof->file); + } else { + fno = _dup(_fileno(iof->file)); + } #else - janet_marshal_int(ctx, fileno(iof->file)); + if (iof->flags & JANET_FILE_NOT_CLOSEABLE) { + fno = fileno(iof->file); + } else { + fno = dup(fileno(iof->file)); + } #endif + janet_marshal_int(ctx, fno); janet_marshal_int(ctx, iof->flags); + janet_marshal_size(ctx, iof->vbufsize); } else { janet_panic("cannot marshal file in safe mode"); } @@ -444,6 +457,11 @@ static void *io_file_unmarshal(JanetMarshalContext *ctx) { } else { iof->flags = flags; } + iof->vbufsize = janet_unmarshal_size(ctx); + if (iof->vbufsize != BUFSIZ) { + int result = setvbuf(iof->file, NULL, iof->vbufsize ? _IOFBF : _IONBF, iof->vbufsize); + janet_assert(!result, "unmarshal setvbuf"); + } return iof; } else { janet_panic("cannot unmarshal file in safe mode"); @@ -785,11 +803,11 @@ FILE *janet_getfile(const Janet *argv, int32_t n, int32_t *flags) { } JanetFile *janet_makejfile(FILE *f, int32_t flags) { - return makef(f, flags); + return makef(f, flags, BUFSIZ); } Janet janet_makefile(FILE *f, int32_t flags) { - return janet_wrap_abstract(makef(f, flags)); + return janet_wrap_abstract(makef(f, flags, BUFSIZ)); } JanetAbstract janet_checkfile(Janet j) { diff --git a/src/include/janet.h b/src/include/janet.h index e1a5c79a..ac2e3019 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -1281,6 +1281,7 @@ typedef struct JanetFile JanetFile; struct JanetFile { FILE *file; int32_t flags; + size_t vbufsize; }; /* For janet_try and janet_restore */ diff --git a/test/suite-ev2.janet b/test/suite-ev2.janet index c94a2d86..caa323a4 100644 --- a/test/suite-ev2.janet +++ b/test/suite-ev2.janet @@ -84,4 +84,21 @@ (assert-error "cannot schedule non-new fiber" (ev/go f)) +# IO file copying +(os/mkdir "tmp") +(def f-original (file/open "tmp/out.txt" :wb)) +(xprin f-original "hello\n") +(file/flush f-original) +(ev/do-thread + # Closes a COPY of the original file, otherwise we get a user-after-close file descriptor + (:close f-original)) +(def g-original (file/open "tmp/out2.txt" :wb)) +(xprin g-original "world1\n") +(xprin f-original "world2\n") +(:close f-original) +(xprin g-original "abc\n") +(:close g-original) +(assert (deep= @"hello\nworld2\n" (slurp "tmp/out.txt")) "file threading 1") +(assert (deep= @"world1\nabc\n" (slurp "tmp/out2.txt")) "file threading 2") + (end-suite)