-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Use clonefile instead of copyfile on macOS. #10020
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
Conversation
|
I went through the build failures and they seem to be unrelated. |
kumpera
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't reviewed the large changes to the IO code itself.
There are some bits that require fixing/changing.
mono/metadata/w32file-unix.c
Outdated
| #endif | ||
| } | ||
|
|
||
| #if __APPLE__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should use the HOST_ defines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with changing it, but there were already other pieces of code using __APPLE__, so I just followed whatever was already there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HOST_DARWIN?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@filipnavara yes.
mono/metadata/w32file-unix.c
Outdated
| finds = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, finds_remove); | ||
| mono_coop_mutex_init (&finds_mutex); | ||
|
|
||
| #if __APPLE__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is should use HOST_ defines.
mono/metadata/w32file-unix.c
Outdated
| mono_coop_mutex_init (&finds_mutex); | ||
|
|
||
| #if __APPLE__ | ||
| clonefile_ptr = (clonefile_fn)dlsym (RTLD_DEFAULT, "clonefile"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAICT this won't work on iOS or watchOS. @rolfbjarne can you give us a more authoritative answer here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We must not use RTLD_DEFAULT as it will cause us all sorts of trouble with embeders and fullAOT scenarios.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd appreciate any suggestions on how to fix it. I assumed RTLD_DEFAULT is ok since it's a system API (libc, or libsystem respectively).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something like
libc_handle = dlopen("/usr/lib/libc.dylib", RTLD_NOW);
clonefile_ptr = (clonefile_fn)dlsym (libc_handle, "clonefile");?
How about iOS? I'd be fine with supporting macOS only if dlsym is a problem.
mono/metadata/w32file-unix.c
Outdated
| #ifdef HAVE_DIRENT_H | ||
| # include <dirent.h> | ||
| #endif | ||
| #if __APPLE__ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be a HAVE_DLFCN_H define?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically yes, but the assumption was that all Apple platforms have it anyway.
mono/metadata/w32file-unix.c
Outdated
| { | ||
| gchar *located_from, *located_to; | ||
| int ret; | ||
| if (clonefile_ptr != NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you check clonefile_ptr before calling _wapi_clonefile, you can just g_assert(clonefile_ptr) here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to assert as you suggested.
mono/metadata/w32file-unix.c
Outdated
| MONO_EXIT_GC_SAFE; | ||
| MONO_ENTER_GC_SAFE; | ||
| ret = clonefile_ptr ( | ||
| located_from == NULL ? from : located_from, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid worrying about precedence I like to reverse this:
foo ? foo : other
But I realize this is how it was.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer to keep it unchanged to keep the diff smaller. I'll remember your advice when writing new code.
|
@monojenkins build failed |
|
@kumpera could you please take another look at it? |
mono/metadata/w32file-unix.c
Outdated
| #if HOST_DARWIN | ||
| libc_handle = dlopen ("/usr/lib/libc.dylib", 0); | ||
| g_assert (libc_handle); | ||
| clonefile_ptr = (clonefile_fn)dlsym (RTLD_DEFAULT, "clonefile"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're not using libc_handle I don't get why are we dlopen'ing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh, my fault, should be used instead of RTLD_DEFAULT
kumpera
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
@monojenkins backport to 2018-08 |
|
@monojenkins backport to 2018-06 |
|
@luhenry backporting to 2018-06 failed, the patch results in conflicts: Please backport manually! |
* Use clonefile instead of copyfile on macOS. * Address PR review comments. * Address PR review comments (if -> assert). * RTLD_DEFAULT - > libc_handle
[2018-06] Use clonefile instead of copyfile on macOS * Revert of #10010 * Backport of #10020 Fixes #10447 /cc @filipnavara
* Use clonefile instead of copyfile on macOS. * Address PR review comments. * Address PR review comments (if -> assert). * RTLD_DEFAULT - > libc_handle Commit migrated from mono/mono@583bae5
Alternative to #10008.
Note that
copyfileis completely user-mode API implemented in/usr/lib/system/libcopyfile.dylib. As you can see in the source code in thecopyfile_datamethod it does exactly the same read+write loop as Mono and offers no performance benefits by itself.Someone in Apple decided to break the
copyfileAPI in macOS 10.13.2 by cloning symlinks instead of targets despite the fact that passed in flags do not includeCOPYFILE_NOFOLLOW_SRC. The reason for the change is also completely bogus - we don't support copying directories, so let's not follow symlinks because they could point to directories. Well, just before callingclonefilethey check if the source is a link, so they could have skipped cloning symlinks instead.Since the broken
copyfileis apparently in the wild already the only way to fix it is to drop using it for cloning. And since cloning was the only performance benefit of the API it makes sense to drop its usage entirely.