Index: lib/profile/GCDAProfiling.c =================================================================== --- lib/profile/GCDAProfiling.c +++ lib/profile/GCDAProfiling.c @@ -341,38 +341,26 @@ COMPILER_RT_VISIBILITY void llvm_gcda_start_file(const char *orig_filename, const char version[4], uint32_t checksum) { - const char *mode = "r+b"; filename = mangle_filename(orig_filename); - - /* Try just opening the file. */ new_file = 0; - fd = open(filename, O_RDWR | O_BINARY); + fd = lprofOpenFile(filename, &new_file); if (fd == -1) { - /* Try opening the file, creating it if necessary. */ - new_file = 1; - mode = "w+b"; - fd = open(filename, O_RDWR | O_CREAT | O_BINARY, 0644); - if (fd == -1) { - /* Try creating the directories first then opening the file. */ - __llvm_profile_recursive_mkdir(filename); - fd = open(filename, O_RDWR | O_CREAT | O_BINARY, 0644); - if (fd == -1) { - /* Bah! It's hopeless. */ - int errnum = errno; - fprintf(stderr, "profiling: %s: cannot open: %s\n", filename, - strerror(errnum)); - return; - } - } + /* Bah! It's hopeless. */ + fprintf(stderr, "profiling: %s: cannot open: %s\n", filename, + strerror(errno)); + return; } /* Try to flock the file to serialize concurrent processes writing out to the * same GCDA. This can fail if the filesystem doesn't support it, but in that * case we'll just carry on with the old racy behaviour and hope for the best. */ - lprofLockFd(fd); - output_file = fdopen(fd, mode); + if (lprofLockFd(fd) != 0) { + fprintf(stderr, "profiling: %s: cannot lock: %s\n", filename, + strerror(errno)); + } + output_file = fdopen(fd, new_file ? "w+b" : "r+b"); /* Initialize the write buffer. */ write_buffer = NULL; Index: lib/profile/InstrProfilingUtil.h =================================================================== --- lib/profile/InstrProfilingUtil.h +++ lib/profile/InstrProfilingUtil.h @@ -24,6 +24,8 @@ int lprofLockFd(int fd); int lprofUnlockFd(int fd); +int lprofOpenOrCreateFile(const char *filename, int *newfile); +int lprofOpenFile(char *filename, int *newfile); /*! Open file \c Filename for read+write with write * lock for exclusive access. The caller will block Index: lib/profile/InstrProfilingUtil.c =================================================================== --- lib/profile/InstrProfilingUtil.c +++ lib/profile/InstrProfilingUtil.c @@ -7,6 +7,8 @@ |* \*===----------------------------------------------------------------------===*/ +#include + #ifdef _WIN32 #include #include @@ -16,7 +18,6 @@ #include #include #include -#include #include #endif @@ -125,8 +126,7 @@ } return 0; #else - flock(fd, LOCK_EX); - return 0; + return flock(fd, LOCK_EX); #endif } @@ -150,8 +150,7 @@ } return 0; #else - flock(fd, LOCK_UN); - return 0; + return flock(fd, LOCK_UN); #endif } @@ -288,3 +287,25 @@ prctl(PR_SET_PDEATHSIG, SIGKILL); #endif } + +COMPILER_RT_VISIBILITY +int lprofOpenOrCreateFile(const char *filename, int *newfile) { + int fd = open(filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0644); + if (fd == -1 && errno == EEXIST) { + return open(filename, O_RDWR | O_BINARY); + } + *newfile = 1; + return fd; +} + +COMPILER_RT_VISIBILITY +int lprofOpenFile(char *filename, int *newfile) { + int fd = lprofOpenOrCreateFile(filename, newfile); + if (fd == -1) { + /* Try creating the directories first then opening the file. */ + __llvm_profile_recursive_mkdir(filename); + *newfile = 0; + return lprofOpenOrCreateFile(filename, newfile); + } + return fd; +} Index: test/profile/Inputs/instrprof-gcov-prefix.c =================================================================== --- /dev/null +++ test/profile/Inputs/instrprof-gcov-prefix.c @@ -0,0 +1 @@ +int main() { return 0; } Index: test/profile/Posix/instrprof-gcov-prefix.test =================================================================== --- /dev/null +++ test/profile/Posix/instrprof-gcov-prefix.test @@ -0,0 +1,16 @@ +RUN: mkdir -p %t.d +RUN: cd %t.d + +RUN: rm -f instrprof-gcov-prefix.gcno instrprof-gcov-prefix.gcda +RUN: %clang --coverage -o %t %S/../Inputs/instrprof-gcov-prefix.c +RUN: test -f instrprof-gcov-prefix.gcno +RUN: %run %t +RUN: test -f instrprof-gcov-prefix.gcda +RUN: rm -f instrprof-gcov-prefix.gcno instrprof-gcov-prefix.gcda + +RUN: rm -fr %t.d/dir1 +RUN: GCOV_PREFIX=%t.d/dir1/dir2/dir3 %run %t +RUN: GCOV_PREFIX=%t.d/dir1/dir2/dir3 %run %t +RUN: test ! -f instrprof-gcov-prefix.gcda +RUN: test -f %t.d/dir1/dir2/dir3/`pwd`/instrprof-gcov-prefix.gcda +RUN: rm -fr %t.d/dir1