roast
roast copied to clipboard
Change directory to $*TMPDIR
Fixes https://github.com/Raku/roast/issues/718
My opinion: put temporary files into TMPDIR. That's what it's for. roast has traditionally littered directories and I'd like to get rid of that. On the contrary, it should set a good example.
As to safely creating a temp file, the best option is to rely on POSIX' mkstemp() or mkstemps() functions. These combine secure file name generation with atomic check and open.
The only safe alternative is to set the O_CREAT and O_EXCL flags, so that if the file already exists, the openat() call errors with EEXIST and then loop until you find an untaken name. The File::Temp module uses this approach.
Just for completeness as I don't think it would work here: on Linux even better than mkstemp is openat() with the O_TMPFILE flag which creates an unnamed temporary file, so there can never be any name clash and no security issues due to predictable temp file names. Of course that doesn't work if you need the file to be available to other processes. Unless those processes are fork()ed or you pass the file descriptor via a pipe.
FWIW the whole discussion shows why I wished that we included secure temporary file creation in Raku itself. Temporary files are a very common need and creating them is something most people get wrong as the wronger a way is, the easier it seems to be.
My bad, I haven't done it in first place, but a search in packages/Test-Helpers came up with make-temp-*
family of routines in Test::Util
. Moreover, they record all files/dirs created and wipe them out in END
phaser.
I tried out the patch and I'm afraid it doesn't really work as intended. For me (on FreeBSD 12.4) the socket files are created in the directory where I start rakudo-m
-- and not in $*TMPDIR
.
I'm not totally sure about the why, but from what I've seen the C code that actually creates the socket file (IIUC it's the bind
in https://github.com/MoarVM/MoarVM/blob/6b456a6c05/src/io/syncsocket.c#L453) has its current working directory unchanged -- it's still the directory where I started rakudo-m
. Since bind
only gets a (relative) file name in dest->sa_data
the socket file is not created in /tmp
, but in the "start directory".
But maybe we should just use an absolute path instead of a relative one. (There's still the potential problem with $*TMPDIR
already having a long path, but that's probably manageable by the user who wants to run the tests.) I'll open an alternative PR ...
Alternative PR: https://github.com/Raku/roast/pull/829