Merge remote-tracking branch 'origin/swift-4.0-branch' into stable

* origin/swift-4.0-branch:
  [PGO] Suspend SIGKILL for PR_SET_PDEATHSIG in profile-write
  [PGO] Delay profile dir creation until write
  [compiler-rt][asan|win] Fix flaky unittest due to large allocations
diff --git a/lib/profile/InstrProfilingFile.c b/lib/profile/InstrProfilingFile.c
index 9a11a10..3ee34b9 100644
--- a/lib/profile/InstrProfilingFile.c
+++ b/lib/profile/InstrProfilingFile.c
@@ -176,6 +176,16 @@
   return 0;
 }
 
+/* Create the directory holding the file, if needed. */
+static void createProfileDir(const char *Filename) {
+  size_t Length = strlen(Filename);
+  if (lprofFindFirstDirSeparator(Filename)) {
+    char *Copy = (char *)COMPILER_RT_ALLOCA(Length + 1);
+    strncpy(Copy, Filename, Length + 1);
+    __llvm_profile_recursive_mkdir(Copy);
+  }
+}
+
 /* Open the profile data for merging. It opens the file in r+b mode with
  * file locking.  If the file has content which is compatible with the
  * current process, it also reads in the profile data in the file and merge
@@ -188,6 +198,7 @@
   FILE *ProfileFile;
   int rc;
 
+  createProfileDir(ProfileFileName);
   ProfileFile = lprofOpenFileEx(ProfileFileName);
   if (!ProfileFile)
     return NULL;
@@ -237,18 +248,13 @@
   if (!Filename)
     return;
 
-  /* Create the directory holding the file, if needed. */
-  if (lprofFindFirstDirSeparator(Filename)) {
-    char *Copy = (char *)COMPILER_RT_ALLOCA(Length + 1);
-    strncpy(Copy, Filename, Length + 1);
-    __llvm_profile_recursive_mkdir(Copy);
-  }
-
   /* By pass file truncation to allow online raw profile
    * merging. */
   if (lprofCurFilename.MergePoolSize)
     return;
 
+  createProfileDir(Filename);
+
   /* Truncate the file.  Later we'll reopen and append. */
   File = fopen(Filename, "w");
   if (!File)
@@ -586,6 +592,7 @@
   int rc, Length;
   const char *Filename;
   char *FilenameBuf;
+  int PDeathSig = 0;
 
   if (lprofProfileDumped()) {
     PROF_NOTE("Profile data not written to file: %s.\n", 
@@ -612,10 +619,18 @@
     return -1;
   }
 
+  // Temporarily suspend getting SIGKILL when the parent exits.
+  PDeathSig = lprofSuspendSigKill();
+
   /* Write profile data to the file. */
   rc = writeFile(Filename);
   if (rc)
     PROF_ERR("Failed to write file \"%s\": %s\n", Filename, strerror(errno));
+
+  // Restore SIGKILL.
+  if (PDeathSig == 1)
+    lprofRestoreSigKill();
+
   return rc;
 }
 
diff --git a/lib/profile/InstrProfilingUtil.c b/lib/profile/InstrProfilingUtil.c
index 321c719..d116041 100644
--- a/lib/profile/InstrProfilingUtil.c
+++ b/lib/profile/InstrProfilingUtil.c
@@ -29,6 +29,11 @@
 #include <stdlib.h>
 #include <string.h>
 
+#if defined(__linux__)
+#include <signal.h>
+#include <sys/prctl.h>
+#endif
+
 COMPILER_RT_VISIBILITY
 void __llvm_profile_recursive_mkdir(char *path) {
   int i;
@@ -219,3 +224,24 @@
 #endif
   return Sep;
 }
+
+COMPILER_RT_VISIBILITY int lprofSuspendSigKill() {
+#if defined(__linux__)
+  int PDeachSig = 0;
+  /* Temporarily suspend getting SIGKILL upon exit of the parent process. */
+  if (prctl(PR_GET_PDEATHSIG, &PDeachSig) == 0 && PDeachSig == SIGKILL) {
+    fprintf(stderr, "set\n");
+    prctl(PR_SET_PDEATHSIG, 0);
+  }
+  return (PDeachSig == SIGKILL);
+#else
+  return 0;
+#endif
+}
+
+COMPILER_RT_VISIBILITY void lprofRestoreSigKill() {
+#if defined(__linux__)
+  fprintf(stderr, "restore \n");
+  prctl(PR_SET_PDEATHSIG, SIGKILL);
+#endif
+}
diff --git a/lib/profile/InstrProfilingUtil.h b/lib/profile/InstrProfilingUtil.h
index a80fde7..9698599 100644
--- a/lib/profile/InstrProfilingUtil.h
+++ b/lib/profile/InstrProfilingUtil.h
@@ -51,4 +51,12 @@
 unsigned lprofBoolCmpXchg(void **Ptr, void *OldV, void *NewV);
 void *lprofPtrFetchAdd(void **Mem, long ByteIncr);
 
+/* Temporarily suspend SIGKILL. Return value of 1 means a restore is needed.
+ * Other return values mean no restore is needed.
+ */
+int lprofSuspendSigKill();
+
+/* Restore previously suspended SIGKILL. */
+void lprofRestoreSigKill();
+
 #endif /* PROFILE_INSTRPROFILINGUTIL_H */
diff --git a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
index 5945ebb..a325b18 100644
--- a/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
@@ -171,7 +171,11 @@
   //   - not thread-safe;
   //   - does not support long traces;
   //   - not tuned for performance.
-  static const uptr kTrEventArrayMaxSize = FIRST_32_SECOND_64(1 << 22, 1 << 30);
+  // Windows doesn't do overcommit (committed virtual memory costs swap), so
+  // programs can't reliably map such large amounts of virtual memory.
+  // TODO(etienneb): Find a way to support coverage of larger executable
+static const uptr kTrEventArrayMaxSize =
+    (SANITIZER_WORDSIZE == 32 || SANITIZER_WINDOWS) ? 1 << 22 : 1 << 30;
   u32 *tr_event_array;
   uptr tr_event_array_size;
   u32 *tr_event_pointer;
diff --git a/test/profile/Linux/instrprof-dir.c b/test/profile/Linux/instrprof-dir.c
new file mode 100644
index 0000000..9d9af6d
--- /dev/null
+++ b/test/profile/Linux/instrprof-dir.c
@@ -0,0 +1,13 @@
+// RUN: %clang_pgogen -o %t %s
+// RUN: env LLVM_PROFILE_FILE="%t.d/%m.profraw"
+// RUN: rm -fr %t.d
+// RUN: %run %t %t.d
+
+#include <errno.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+  if (access(argv[1], F_OK) == 0)
+    return 1; // %t.d should not exist yet.
+  return !(errno == ENOENT);
+}
diff --git a/test/profile/Linux/prctl.c b/test/profile/Linux/prctl.c
new file mode 100644
index 0000000..43baf65
--- /dev/null
+++ b/test/profile/Linux/prctl.c
@@ -0,0 +1,36 @@
+// RUN: %clang_pgogen -O2 -o %t %s
+// RUN: rm -rf default_*.profraw
+// RUN: %run %t && sleep 1
+// RUN: llvm-profdata show default_*.profraw 2>&1 | FileCheck %s
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+
+#define FAKE_COUNT_SZ 2000000
+/* fake counts to increse the profile size. */
+unsigned long long __attribute__((section("__llvm_prf_cnts")))
+counts[FAKE_COUNT_SZ];
+
+int main(int argc, char **argv) {
+  pid_t pid = fork();
+  if (pid == 0) {
+    int i;
+    int sum = 0;
+    /* child process: sleep 500us and get to runtime before the
+     * main process exits. */
+    prctl(PR_SET_PDEATHSIG, SIGKILL);
+    usleep(500);
+    for (i = 0; i < 5000; ++i)
+      sum += i * i * i;
+    printf("child process (%d): sum=%d\n", getpid(), sum);
+  } else if (pid > 0) {
+    /* parent process: sleep 100us to get into profile runtime first. */
+    usleep(100);
+  }
+  return 0;
+}
+
+// CHECK-NOT: Empty raw profile file