Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fs: add mkstemp functions #33549

Closed
wants to merge 7 commits into from
Closed

fs: add mkstemp functions #33549

wants to merge 7 commits into from

Conversation

targos
Copy link
Member

@targos targos commented May 25, 2020

  • fs.mkstemp and fs.mkstempSync return path and fd.
  • fsPromises.mkstemp returns path and handle.

@nodejs/fs

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

* fs.mkstemp and fs.mkstempSync return `path` and `fd`.
* fsPromises.mkstemp returns `path` and `handle`.
@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. labels May 25, 2020
@targos targos added fs Issues and PRs related to the fs subsystem / file system. semver-minor PRs that contain new features and should be released in the next minor version. and removed lib / src Issues and PRs related to general changes in the lib or src directory. labels May 25, 2020
@targos
Copy link
Member Author

targos commented May 25, 2020

/cc @addaleax

src/node_file.cc Outdated Show resolved Hide resolved
Copy link
Member

@vdeturckheim vdeturckheim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nodejs-github-bot

This comment has been minimized.

@nodejs-github-bot

This comment has been minimized.

@nodejs-github-bot
Copy link
Collaborator

doc/api/fs.md Outdated Show resolved Hide resolved
doc/api/fs.md Outdated Show resolved Hide resolved
@benjamingr
Copy link
Member

I think a disposer API for the promises side would have been nicer. I maintain tmp-promise and in my experience that's the more popular API.

I'd also steal some tests from tmp but that can be in a follow up PR :]

@benjamingr benjamingr closed this May 25, 2020
@benjamingr benjamingr reopened this May 25, 2020
doc/api/fs.md Outdated Show resolved Hide resolved
Co-authored-by: Benjamin Gruenbaum <[email protected]>
@targos
Copy link
Member Author

targos commented May 25, 2020

I think a disposer API for the promises side would have been nicer. I maintain tmp-promise and in my experience that's the more popular API.

I'd also steal some tests from tmp but that can be in a follow up PR :]

I don't understand what you are suggesting, sorry.

@benjamingr
Copy link
Member

@targos in tmp-promise there are two APIs, one is similar to the one outlined here and the other looks a bit like

fs.promises.withMkstemp(async (file) => {
  // when the promise returned from this async function settles, file is automatically closed
});

This makes for better error handling most of the time. I am not saying we should ship this sort of API or that if we do we shouldn't ship the one already in this PR - only that in my (anecdotal) experience as a maintainer of tmp-promise it's the more popular one.

doc/api/fs.md Show resolved Hide resolved
@targos
Copy link
Member Author

targos commented May 25, 2020

@nodejs-github-bot
Copy link
Collaborator

@targos
Copy link
Member Author

targos commented May 30, 2020

@nodejs/platform-aix PTAL

@richardlau
Copy link
Member

I can take a look on Monday but my suspicion would be that the value of the template (i.e. req->path) passed into the mkstemp C call on completion is undefined in the error case.

Copy link
Member

@bnoordhuis bnoordhuis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. The AIX failure looks like it's happening on the libuv or libc level. Needs further investigation but I don't think it's caused by this PR.

@bnoordhuis
Copy link
Member

That sounds plausible. POSIX allows it to be unspecified. I'll open a libuv PR to clobber req->path on error to flush out such applications bugs.

@targos targos added the blocked PRs that are blocked by other issues or PRs. label May 31, 2020
@BridgeAR BridgeAR force-pushed the master branch 2 times, most recently from 8ae28ff to 2935f72 Compare May 31, 2020 12:18
@richardlau
Copy link
Member

I can take a look on Monday but my suspicion would be that the value of the template (i.e. req->path) passed into the mkstemp C call on completion is undefined in the error case.

Yes, looks like that's the case here:

diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index f5b2b94207..ce9683cb51 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -336,7 +336,9 @@ static int uv__fs_mkstemp(uv_fs_t* req) {
   if (req->cb != NULL)
     uv_rwlock_rdlock(&req->loop->cloexec_lock);

+printf("before mkstemp, path: %s\n", path);
   r = mkstemp(path);
+printf("after mkstemp, path: %s\n", path);

   /* In case of failure `uv__cloexec` will leave error in `errno`,
    * so it is enough to just set `r` to `-1`.
bash-4.4$ ./tools/test.py parallel/test-fs-error-messages
=== release test-fs-error-messages ===
Path: parallel/test-fs-error-messages
before mkstemp, path: /home/riclau/sandbox/github/nodejs/test/.tmp.0/non-existent/foo/barXXXXXX
after mkstemp, path:
before mkstemp, path: /home/riclau/sandbox/github/nodejs/test/.tmp.0/non-existent/foo/barXXXXXX
after mkstemp, path:
(node:13172966) internal/test/binding: These APIs are for internal testing only. Do not use them.
(Use `node --trace-warnings ...` to show where the warning was created)
assert.js:920
    throw err;
    ^

AssertionError [ERR_ASSERTION]: The input did not match the regular expression /^\/home\/riclau\/sandbox\/github\/nodejs\/test\/\.tmp\.0\/non\-existent\/foo\/bar/. Input:

''

    at validateError (/home/riclau/sandbox/github/nodejs/test/parallel/test-fs-error-messages.js:670:12)
    at /home/riclau/sandbox/github/nodejs/test/common/index.js:363:15
    at fs.js:163:23
    at FSReqCallback.oncomplete (fs.js:1893:14) {
  generatedMessage: true,
  code: 'ERR_ASSERTION',
  actual: '',
  expected: /^\/home\/riclau\/sandbox\/github\/nodejs\/test\/\.tmp\.0\/non\-existent\/foo\/bar/,
  operator: 'match'
}
Command: out/Release/node --expose-internals /home/riclau/sandbox/github/nodejs/test/parallel/test-fs-error-messages.js
[00:00|% 100|+   0|-   1]: Done
bash-4.4$

POSIX doesn't specify what happens to the template string in the error case: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdtemp.html

The Linux documentation also points out that the template may be undefined for some errors (EEXIST): https://www.man7.org/linux/man-pages/man3/mkstemp.3.html

So it's not safe to assume the contents of the template (req->path) if the mkstemp call fails as the test is currently doing. If we deem it useful from a debugging/errors point of view in Node.js we should probably store a copy of the template before making the call into libuv.

@addaleax addaleax removed the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Jun 19, 2020
@targos
Copy link
Member Author

targos commented Jul 14, 2020

@bnoordhuis I'm not sure anymore. Is this blocked on work that should be done on the libuv side, or should I do something here to fix the issue?

@bnoordhuis
Copy link
Member

@targos There's still some work to be done in libuv but nothing critical, it doesn't have to hold up this PR. I'd go with Richard's suggestion:

we should probably store a copy of the template before making the call into libuv

@targos
Copy link
Member Author

targos commented Jul 14, 2020

I'd go with Richard's suggestion:

we should probably store a copy of the template before making the call into libuv

Okay, can you help me do it? I don't know how I could access the value from the AfterMkstemp callback.

@targos targos added the help wanted Issues that need assistance from volunteers or PRs that need help to proceed. label Jul 17, 2020
vtjnash pushed a commit to libuv/libuv that referenced this pull request Aug 12, 2020
Contents of template variable passed for posix call mkstemp on error
code EINVAL is unknown. On AIX platform, template will get clobbered
on EINVAL and any attempt to read template might result in error.

In libuv, req->path is passed directly to the mkstemp call and
behavior of this string on error is platform dependent. To avoid
portability issues, it's better to have a common behavior on all
platform. For both unix and windows platform libuv will rewrite path
with an empty string on all error cases.

Fixes: #2913
Refs: nodejs/node#33549
Refs: #2933
PR-URL: #2938
Reviewed-By: Jameson Nash <[email protected]>
@aduh95
Copy link
Contributor

aduh95 commented Oct 16, 2020

@targos does the change made to libuv by @vtjnash help unblock this?

@targos
Copy link
Member Author

targos commented Oct 17, 2020

It doesn't. I still need help for #33549 (comment)

JeffroMF pushed a commit to JeffroMF/libuv that referenced this pull request May 16, 2022
Contents of template variable passed for posix call mkstemp on error
code EINVAL is unknown. On AIX platform, template will get clobbered
on EINVAL and any attempt to read template might result in error.

In libuv, req->path is passed directly to the mkstemp call and
behavior of this string on error is platform dependent. To avoid
portability issues, it's better to have a common behavior on all
platform. For both unix and windows platform libuv will rewrite path
with an empty string on all error cases.

Fixes: libuv#2913
Refs: nodejs/node#33549
Refs: libuv#2933
PR-URL: libuv#2938
Reviewed-By: Jameson Nash <[email protected]>
@mschfh
Copy link

mschfh commented Aug 22, 2023

it doesn't have to hold up this PR

If we deem it useful from a debugging/errors point of view in Node.js we should probably store a copy of the template before making the call into libuv.

Could this PR be merged and the enhancement be added later on?

@BrianJDrake
Copy link

This pull request would complete the old feature request #5332.

@targos
Copy link
Member Author

targos commented Oct 17, 2023

Anyone feel free to take this over. I'm not able to fix the problems and I don't need the feature myself.

@targos targos closed this Oct 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked PRs that are blocked by other issues or PRs. c++ Issues and PRs that require attention from people who are familiar with C++. fs Issues and PRs related to the fs subsystem / file system. help wanted Issues that need assistance from volunteers or PRs that need help to proceed. semver-minor PRs that contain new features and should be released in the next minor version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.