Reland "[vm] resolve symbolic link to find kernel_service snapshot"

This is a reland of 8a8c19dd4b

Fix the memory leak of namespace.

Original change's description:
> [vm] resolve symbolic link to find kernel_service snapshot
>
> When VM starts, it will try to find kernel service snapshot which is located together with exe file. However, if symbolic link is provided, the directory to search will become the parent directory of link but not the actual target.
> This cl will resolve the symbolic link to find the kernel service snapshot.
>
> Bug: https://github.com/dart-lang/sdk/issues/35188
> Change-Id: I842973a9b73439003a748122d9416158d155892e
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/129380
> Commit-Queue: Zichang Guo <zichangguo@google.com>
> Reviewed-by: Siva Annamalai <asiva@google.com>

Bug: https://github.com/dart-lang/sdk/issues/35188
Change-Id: I45f09d3ec813926b72d79880aeee2cc8a0453f87
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133246
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Zichang Guo <zichangguo@google.com>
This commit is contained in:
Zichang Guo 2020-01-24 19:28:57 +00:00 committed by commit-bot@chromium.org
parent 22d55c39d8
commit aa1b00d668
7 changed files with 89 additions and 30 deletions

View file

@ -55,6 +55,16 @@ static char* GetDirectoryPrefixFromExeName() {
name = Platform::GetExecutableName();
target_size = strlen(name);
}
Namespace* namespc = Namespace::Create(Namespace::Default());
if (File::GetType(namespc, name, false) == File::kIsLink) {
// Resolve the link without creating Dart scope String.
name = File::LinkTarget(namespc, name, target, kTargetSize);
if (name == NULL) {
return strdup("");
}
target_size = strlen(name);
}
namespc->Release();
const char* sep = File::PathSeparator();
const intptr_t sep_length = strlen(sep);

View file

@ -253,7 +253,12 @@ class File : public ReferenceCounted<File> {
static StdioHandleType GetStdioHandleType(int fd);
// LinkTarget, GetCanonicalPath, and ReadLink may call Dart_ScopeAllocate.
static const char* LinkTarget(Namespace* namespc, const char* pathname);
// If dest and its size are provided, Dart String will not be created.
// The result will be populated into dest.
static const char* LinkTarget(Namespace* namespc,
const char* pathname,
char* dest = NULL,
int dest_size = 0);
static const char* GetCanonicalPath(Namespace* namespc, const char* path);
// Link LinkTarget, but pathname must be absolute.
static const char* ReadLink(const char* pathname);

View file

@ -552,7 +552,10 @@ static int ReadLinkAt(int dirfd,
return syscall(__NR_readlinkat, dirfd, pathname, buf, bufsize);
}
const char* File::LinkTarget(Namespace* namespc, const char* name) {
const char* File::LinkTarget(Namespace* namespc,
const char* name,
char* dest,
int dest_size) {
NamespaceScope ns(namespc, name);
struct stat link_stats;
const int status = TEMP_FAILURE_RETRY(
@ -574,11 +577,17 @@ const char* File::LinkTarget(Namespace* namespc, const char* name) {
if (target_size <= 0) {
return NULL;
}
char* target_name = DartUtils::ScopedCString(target_size + 1);
ASSERT(target_name != NULL);
memmove(target_name, target, target_size);
target_name[target_size] = '\0';
return target_name;
if (dest == NULL) {
dest = DartUtils::ScopedCString(target_size + 1);
} else {
ASSERT(dest_size > 0);
if (dest_size <= target_size) {
return NULL;
}
}
memmove(dest, target, target_size);
dest[target_size] = '\0';
return dest;
}
bool File::IsAbsolutePath(const char* pathname) {

View file

@ -540,7 +540,10 @@ bool File::SetLastModified(Namespace* namespc,
return utimensat(ns.fd(), ns.path(), times, 0) == 0;
}
const char* File::LinkTarget(Namespace* namespc, const char* name) {
const char* File::LinkTarget(Namespace* namespc,
const char* name,
char* dest,
int dest_size) {
NamespaceScope ns(namespc, name);
struct stat link_stats;
const int status = TEMP_FAILURE_RETRY(
@ -562,11 +565,17 @@ const char* File::LinkTarget(Namespace* namespc, const char* name) {
if (target_size <= 0) {
return NULL;
}
char* target_name = DartUtils::ScopedCString(target_size + 1);
ASSERT(target_name != NULL);
memmove(target_name, target, target_size);
target_name[target_size] = '\0';
return target_name;
if (dest == NULL) {
dest = DartUtils::ScopedCString(target_size + 1);
} else {
ASSERT(dest_size > 0);
if (dest_size <= target_size) {
return NULL;
}
}
memmove(dest, target, target_size);
dest[target_size] = '\0';
return dest;
}
bool File::IsAbsolutePath(const char* pathname) {

View file

@ -549,7 +549,10 @@ bool File::SetLastModified(Namespace* namespc,
return utimensat(ns.fd(), ns.path(), times, 0) == 0;
}
const char* File::LinkTarget(Namespace* namespc, const char* name) {
const char* File::LinkTarget(Namespace* namespc,
const char* name,
char* dest,
int dest_size) {
NamespaceScope ns(namespc, name);
struct stat64 link_stats;
const int status = TEMP_FAILURE_RETRY(
@ -571,11 +574,17 @@ const char* File::LinkTarget(Namespace* namespc, const char* name) {
if (target_size <= 0) {
return NULL;
}
char* target_name = DartUtils::ScopedCString(target_size + 1);
ASSERT(target_name != NULL);
memmove(target_name, target, target_size);
target_name[target_size] = '\0';
return target_name;
if (dest == NULL) {
dest = DartUtils::ScopedCString(target_size + 1);
} else {
ASSERT(dest_size > 0);
if (dest_size <= target_size) {
return NULL;
}
}
memmove(dest, target, target_size);
dest[target_size] = '\0';
return dest;
}
bool File::IsAbsolutePath(const char* pathname) {

View file

@ -518,7 +518,10 @@ bool File::SetLastModified(Namespace* namespc,
return utime(name, &times) == 0;
}
const char* File::LinkTarget(Namespace* namespc, const char* pathname) {
const char* File::LinkTarget(Namespace* namespc,
const char* pathname,
char* dest,
int dest_size) {
struct stat link_stats;
if (lstat(pathname, &link_stats) != 0) {
return NULL;
@ -536,11 +539,17 @@ const char* File::LinkTarget(Namespace* namespc, const char* pathname) {
if (target_size <= 0) {
return NULL;
}
char* target_name = DartUtils::ScopedCString(target_size + 1);
ASSERT(target_name != NULL);
memmove(target_name, target, target_size);
target_name[target_size] = '\0';
return target_name;
if (dest == NULL) {
dest = DartUtils::ScopedCString(target_size + 1);
} else {
ASSERT(dest_size > 0);
if ((size_t)dest_size <= target_size) {
return NULL;
}
}
memmove(dest, target, target_size);
dest[target_size] = '\0';
return dest;
}
bool File::IsAbsolutePath(const char* pathname) {

View file

@ -517,7 +517,10 @@ int64_t File::LengthFromPath(Namespace* namespc, const char* name) {
return st.st_size;
}
const char* File::LinkTarget(Namespace* namespc, const char* pathname) {
const char* File::LinkTarget(Namespace* namespc,
const char* pathname,
char* dest,
int dest_size) {
const wchar_t* name = StringUtilsWin::Utf8ToWide(pathname);
HANDLE dir_handle = CreateFileW(
name, GENERIC_READ,
@ -571,13 +574,18 @@ const char* File::LinkTarget(Namespace* namespc, const char* pathname) {
}
int utf8_length = WideCharToMultiByte(CP_UTF8, 0, target, target_length, NULL,
0, NULL, NULL);
char* utf8_target = DartUtils::ScopedCString(utf8_length + 1);
if (0 == WideCharToMultiByte(CP_UTF8, 0, target, target_length, utf8_target,
if (dest_size > 0 && dest_size <= utf8_length) {
return NULL;
}
if (dest == NULL) {
dest = DartUtils::ScopedCString(utf8_length + 1);
}
if (0 == WideCharToMultiByte(CP_UTF8, 0, target, target_length, dest,
utf8_length, NULL, NULL)) {
return NULL;
}
utf8_target[utf8_length] = '\0';
return utf8_target;
dest[utf8_length] = '\0';
return dest;
}
void File::Stat(Namespace* namespc, const char* name, int64_t* data) {