Repository: JuliaLang/julia
File: base/file.jl (Julia)

Code before:
temp_cleanup_purge(; force=false) = force ? temp_cleanup_purge_all() : @lock TEMP_CLEANUP_LOCK temp_cleanup_purge_prelocked(false)

function temp_cleanup_postprocess(cleanup_dirs)
    if !isempty(cleanup_dirs)
        rmcmd = """
        eof(stdin)
        for path in eachline(stdin)
            try
                rm(path, force=true, recursive=true)
            catch ex
                @warn "Failed to clean up temporary path \$(repr(path))\n\$ex" _group=:file
            end
        end
        """
        cmd = Cmd(Base.cmd_gen(((Base.julia_cmd(),), ("--startup-file=no",), ("-e",), (rmcmd,))); ignorestatus = true, detach = true)
        pw = Base.PipeEndpoint()
        rd, wr = Base.link_pipe(true, true)
        try
            Base.open_pipe!(pw, wr)
        catch
            Base.close_pipe_sync(wr)
            rethrow()
        end
        run(cmd, rd, devnull, stderr; wait=false)
        join(pw, cleanup_dirs, "\n")
        Base.dup(wr) # intentionally leak a reference, until the process exits
        close(pw)
    end
end

function temp_cleanup_atexit()
    temp_cleanup_purge_all()
    temp_cleanup_postprocess(keys(TEMP_CLEANUP))
end

function __postinit__()
    Base.atexit(temp_cleanup_atexit)
end

const temp_prefix = "jl_"

# Use `Libc.rand()` to generate random strings
function _rand_filename(len = 10)
    slug = Base.StringVector(len)
    chars = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    for i = 1:len
        slug[i] = chars[(Libc.rand() % length(chars)) + 1]
    end
    return String(slug)
end


Review comment (suggestion):
```suggestion
        run(cmd, pw, devnull, stderr; wait=false)
        join(pw, cleanup_dirs, "\n")
        Base.dup(Base._fd(pw)) # intentionally leak a reference, until the process exits
```

Code after:
end

# deprecated internal function used by some packages
temp_cleanup_purge(; force=false) = force ? temp_cleanup_purge_all() : @lock TEMP_CLEANUP_LOCK temp_cleanup_purge_prelocked(false)

function temp_cleanup_postprocess(cleanup_dirs)
    if !isempty(cleanup_dirs)
        rmcmd = """
        cleanuplist = readlines(stdin) # This loop won't start running until stdin is closed, which is supposed to be sequenced after the process exits
        sleep(1) # Wait for the operating system to hopefully be ready, since the OS implementation is probably incorrect, given the history of buggy work-arounds like this that have existed for ages in dotNet and libuv
        for path in cleanuplist
            try
                rm(path, force=true, recursive=true)
            catch ex
                @warn "Failed to clean up temporary path \$(repr(path))\n\$ex" _group=:file
            end
        end
        """
        cmd = Cmd(Base.cmd_gen(((Base.julia_cmd(),), ("--startup-file=no",), ("-e",), (rmcmd,))); ignorestatus = true, detach = true)
        pw = Base.PipeEndpoint()
        run(cmd, pw, devnull, stderr; wait=false)
        join(pw, cleanup_dirs, "\n")
        Base.dup(Base._fd(pw)) # intentionally leak a reference, until the process exits
        close(pw)
    end
end

function temp_cleanup_atexit()
    temp_cleanup_purge_all()
    @lock TEMP_CLEANUP_LOCK temp_cleanup_postprocess(keys(TEMP_CLEANUP))
end

function __postinit__()
    Base.atexit(temp_cleanup_atexit)
end

const temp_prefix = "jl_"

# Use `Libc.rand()` to generate random strings
function _rand_filename(len = 10)
    slug = Base.StringVector(len)
    chars = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    for i = 1:len
        slug[i] = chars[(Libc.rand() % length(chars)) + 1]
    end
    return String(slug)
end


# Obtain a temporary filename.
function tempname(parent::AbstractString=tempdir(); max_tries::Int = 100, cleanup::Bool=true, suffix::AbstractString="")