Keep thread-affine strings on their own thread (fetch unix path, object URLs, worker shell argv)
Closed
DY
3mo ago+125+125+012345678901234567890123456789-72-72-01234567890123456789
What does this PR do?
WTF string refcounts are atomic, but an atomized StringImpl belongs to one thread's atom table and must not be destroyed from another. Three places let a bun_core::String that may be such an impl be dropped (or ref'd) off its thread:
fetch(url, { unix }): the socket path —Utf8Bytesthat can hold a ref into the JS string — was stored inHTTPClientand bitwise-copied to the HTTP thread byptr::read; twoManuallyDrop"forgets" on the redirect paths and aclear_data()reset kept it from being freed twice. It now has the same shape ashostname: theFetchTaskletowns the bytes on the JS thread andHTTPClient<'a>borrows&'a [u8]. The forgets and the reset are gone; no string type is left inbun_httpfor this field.URL.createObjectURL: the registry is process-global, but an entry was a straightdupe()of the creating thread'sBlob, including itsglobal_thisand itsname. A worker thatfetch()ed/imported/revoked that URL cloned and later dropped the creator's name, and got a Blob stamped with the creator's global. Entries are now stored with a null global and ato_thread_safe()name (one copy percreateObjectURLof a namedFile), andresolve_and_dupe(path, global)stamps the resolving thread's global.$0…$NinBun.$inside a worker tookretain_wtf_implon the parent thread'sWorkerOptions.argvstrings and held them for the interpreter's lifetime; it now copies them via the sameworker_option_stringhelperprocess.argvuses.
How did you verify your code works?
New worker.test.ts case: a named File object URL created on the main thread is fetched, imported, .blob()'d and revoked from a worker (and the reverse), and the worker's Bun.$ reads its own argv. Debug+ASAN build driven through fetch over a unix socket, fetch.unix.test.ts, blob.test.ts, bunshell.test.ts, worker.test.ts, serve.test.ts.