Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@filipnavara
Copy link
Contributor

@filipnavara filipnavara commented Aug 10, 2018

Alternative to #10008.

Note that copyfile is completely user-mode API implemented in /usr/lib/system/libcopyfile.dylib. As you can see in the source code in the copyfile_data method it does exactly the same read+write loop as Mono and offers no performance benefits by itself.

Someone in Apple decided to break the copyfile API in macOS 10.13.2 by cloning symlinks instead of targets despite the fact that passed in flags do not include COPYFILE_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 calling clonefile they check if the source is a link, so they could have skipped cloning symlinks instead.

Since the broken copyfile is 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.

@filipnavara filipnavara requested a review from luhenry as a code owner August 10, 2018 10:35
@filipnavara filipnavara changed the title WIP: Use clonefile instead of copyfile on macOS. Use clonefile instead of copyfile on macOS. Aug 10, 2018
@filipnavara
Copy link
Contributor Author

I went through the build failures and they seem to be unrelated.

Copy link
Contributor

@kumpera kumpera left a 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.

#endif
}

#if __APPLE__
Copy link
Contributor

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

Copy link
Contributor Author

@filipnavara filipnavara Aug 10, 2018

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

HOST_DARWIN?

Copy link
Contributor

Choose a reason for hiding this comment

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

finds = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, finds_remove);
mono_coop_mutex_init (&finds_mutex);

#if __APPLE__
Copy link
Contributor

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_coop_mutex_init (&finds_mutex);

#if __APPLE__
clonefile_ptr = (clonefile_fn)dlsym (RTLD_DEFAULT, "clonefile");
Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor Author

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).

Copy link
Contributor Author

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.

#ifdef HAVE_DIRENT_H
# include <dirent.h>
#endif
#if __APPLE__
Copy link
Contributor

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?

Copy link
Contributor Author

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.

{
gchar *located_from, *located_to;
int ret;
if (clonefile_ptr != NULL) {
Copy link
Contributor

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.

Copy link
Contributor Author

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_EXIT_GC_SAFE;
MONO_ENTER_GC_SAFE;
ret = clonefile_ptr (
located_from == NULL ? from : located_from,
Copy link
Contributor

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.

Copy link
Contributor Author

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.

@filipnavara
Copy link
Contributor Author

@monojenkins build failed

@luhenry
Copy link
Contributor

luhenry commented Aug 14, 2018

@kumpera could you please take another look at it?

#if HOST_DARWIN
libc_handle = dlopen ("/usr/lib/libc.dylib", 0);
g_assert (libc_handle);
clonefile_ptr = (clonefile_fn)dlsym (RTLD_DEFAULT, "clonefile");
Copy link
Contributor

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.

Copy link
Contributor Author

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

Copy link
Contributor

@kumpera kumpera left a comment

Choose a reason for hiding this comment

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

LGTM

@luhenry luhenry merged commit 583bae5 into mono:master Aug 15, 2018
@luhenry
Copy link
Contributor

luhenry commented Aug 15, 2018

@monojenkins backport to 2018-08

@luhenry
Copy link
Contributor

luhenry commented Aug 15, 2018

@monojenkins backport to 2018-06

@monojenkins
Copy link
Contributor

@luhenry backporting to 2018-06 failed, the patch results in conflicts:

Applying: Use clonefile instead of copyfile on macOS.
Using index info to reconstruct a base tree...
M	mono/metadata/w32file-unix.c
Falling back to patching base and 3-way merge...
Auto-merging mono/metadata/w32file-unix.c
CONFLICT (content): Merge conflict in mono/metadata/w32file-unix.c
error: Failed to merge in the changes.
Patch failed at 0001 Use clonefile instead of copyfile on macOS.

Please backport manually!

lewurm pushed a commit to lewurm/mono that referenced this pull request Sep 3, 2018
* Use clonefile instead of copyfile on macOS.

* Address PR review comments.

* Address PR review comments (if -> assert).

* RTLD_DEFAULT - > libc_handle
monojenkins added a commit that referenced this pull request Sep 5, 2018
[2018-06] Use clonefile instead of copyfile on macOS

* Revert of #10010 
* Backport of #10020

Fixes #10447


/cc @filipnavara
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
* 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants