Index: lib/asan/asan_rtl.cc
===================================================================
--- lib/asan/asan_rtl.cc
+++ lib/asan/asan_rtl.cc
@@ -469,11 +469,14 @@
 
   if (CAN_SANITIZE_LEAKS) {
     __lsan::InitCommonLsan();
-    if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
-      if (flags()->halt_on_error)
-        Atexit(__lsan::DoLeakCheck);
-      else
-        Atexit(__lsan::DoRecoverableLeakCheckVoid);
+    if (common_flags()->detect_leaks) {
+      __lsan::MaybeStartBackgroundLeakCheckingThread();
+      if (common_flags()->leak_check_at_exit) {
+        if (flags()->halt_on_error)
+          Atexit(__lsan::DoLeakCheck);
+        else
+          Atexit(__lsan::DoRecoverableLeakCheckVoid);
+      }
     }
   }
 
Index: lib/lsan/lsan.cc
===================================================================
--- lib/lsan/lsan.cc
+++ lib/lsan/lsan.cc
@@ -102,8 +102,10 @@
   ThreadStart(tid, GetTid());
   SetCurrentThread(tid);
 
-  if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
-    Atexit(DoLeakCheck);
+  if (common_flags()->detect_leaks) {
+    MaybeStartBackgroundLeakCheckingThread();
+    if (common_flags()->leak_check_at_exit) Atexit(DoLeakCheck);
+  }
 
   InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
 
Index: lib/lsan/lsan_common.h
===================================================================
--- lib/lsan/lsan_common.h
+++ lib/lsan/lsan_common.h
@@ -149,6 +149,11 @@
 void DoRecoverableLeakCheckVoid();
 void DisableCounterUnderflow();
 bool DisabledInThisThread();
+void MaybeRestoreLogPath();
+void MaybeAppendToLogPath();
+
+static const uptr kLeaksIntervalNotSet = 0;
+void MaybeStartBackgroundLeakCheckingThread();
 
 // Used to implement __lsan::ScopedDisabler.
 void DisableInThisThread();
Index: lib/lsan/lsan_common.cc
===================================================================
--- lib/lsan/lsan_common.cc
+++ lib/lsan/lsan_common.cc
@@ -588,6 +588,7 @@
   }
   param.leak_report.ApplySuppressions();
   uptr unsuppressed_count = param.leak_report.UnsuppressedLeakCount();
+  ScopedErrorReportLock l;
   if (unsuppressed_count > 0) {
     Decorator d;
     Printf("\n"
@@ -784,6 +785,26 @@
   return result;
 }
 
+void MaybeRestoreLogPath() {
+  if (common_flags()->leak_check_interval_s == kLeaksIntervalNotSet) return;
+  __sanitizer_set_report_path(common_flags()->log_path);
+}
+
+void MaybeAppendToLogPath() {
+  if (common_flags()->leak_check_interval_s == kLeaksIntervalNotSet) return;
+  const char *log_path = common_flags()->log_path;
+  if (internal_strcmp(log_path, "stderr") == 0 ||
+      internal_strcmp(log_path, "stdout") == 0 || !log_path)
+    return;
+  static char new_log_path[kMaxPathLength] = {'\0'};
+  static const char suffix[] = "in-progress";
+  if (UNLIKELY(new_log_path[0] == '\0')) {
+    internal_snprintf(new_log_path, kMaxPathLength, "%s.%s", log_path, suffix);
+    ScopedErrorReportLock l;
+    __sanitizer_set_report_path(new_log_path);
+  }
+}
+
 } // namespace __lsan
 #else // CAN_SANITIZE_LEAKS
 namespace __lsan {
Index: lib/lsan/lsan_common_linux.cc
===================================================================
--- lib/lsan/lsan_common_linux.cc
+++ lib/lsan/lsan_common_linux.cc
@@ -135,6 +135,25 @@
   dl_iterate_phdr(DoStopTheWorldCallback, &param);
 }
 
+static const int kLeakCheckHandlerSignal = 14;  // SIGALRM
+
+static void LeakCheckTimerHandler(int sig, void *siginfo, void *ucontext) {
+  if (sig != kLeakCheckHandlerSignal) return;
+  ScopedInterceptorDisabler disabler;
+  MaybeAppendToLogPath();
+  TruncateReportFile();
+  DoRecoverableLeakCheckVoid();
+  MaybeRestoreLogPath();
+}
+
+void MaybeStartBackgroundLeakCheckingThread() {
+#if !SANITIZER_GO && SANITIZER_LINUX
+  if (common_flags()->leak_check_interval_s == kLeaksIntervalNotSet) return;
+  internal_start_signal_timer(LeakCheckTimerHandler, kLeakCheckHandlerSignal,
+                              common_flags()->leak_check_interval_s);
+#endif
+}
+
 } // namespace __lsan
 
 #endif // CAN_SANITIZE_LEAKS && SANITIZER_LINUX
Index: lib/lsan/lsan_common_mac.cc
===================================================================
--- lib/lsan/lsan_common_mac.cc
+++ lib/lsan/lsan_common_mac.cc
@@ -202,6 +202,10 @@
   StopTheWorld(callback, argument);
 }
 
+void MaybeStartBackgroundLeakCheckingThread() {
+  UNIMPLEMENTED();
+}
+
 } // namespace __lsan
 
 #endif // CAN_SANITIZE_LEAKS && SANITIZER_MAC
Index: lib/sanitizer_common/sanitizer_common.h
===================================================================
--- lib/sanitizer_common/sanitizer_common.h
+++ lib/sanitizer_common/sanitizer_common.h
@@ -172,6 +172,7 @@
 // IO
 void CatastrophicErrorWrite(const char *buffer, uptr length);
 void RawWrite(const char *buffer);
+void TruncateReportFile();
 bool ColorizeReports();
 void RemoveANSIEscapeSequencesFromString(char *buffer);
 void Printf(const char *format, ...);
@@ -831,6 +832,8 @@
 }
 
 void *internal_start_thread(void(*func)(void*), void *arg);
+void *internal_start_signal_timer(SignalHandlerType handler, int signal,
+                                  uptr interval_s);
 void internal_join_thread(void *th);
 void MaybeStartBackgroudThread();
 
Index: lib/sanitizer_common/sanitizer_file.h
===================================================================
--- lib/sanitizer_common/sanitizer_file.h
+++ lib/sanitizer_common/sanitizer_file.h
@@ -27,6 +27,7 @@
   void Write(const char *buffer, uptr length);
   bool SupportsColors();
   void SetReportPath(const char *path);
+  void Truncate();
 
   // Don't use fields directly. They are only declared public to allow
   // aggregate initialization.
@@ -52,7 +53,8 @@
 enum FileAccessMode {
   RdOnly,
   WrOnly,
-  RdWr
+  RdWr,
+  WrTrunc
 };
 
 // Returns kInvalidFd on error.
Index: lib/sanitizer_common/sanitizer_file.cc
===================================================================
--- lib/sanitizer_common/sanitizer_file.cc
+++ lib/sanitizer_common/sanitizer_file.cc
@@ -34,6 +34,8 @@
   report_file.Write(buffer, internal_strlen(buffer));
 }
 
+void TruncateReportFile() { report_file.Truncate(); }
+
 void ReportFile::ReopenIfNecessary() {
   mu->CheckLocked();
   if (fd == kStdoutFd || fd == kStderrFd) return;
@@ -93,6 +95,16 @@
   }
 }
 
+void ReportFile::Truncate() {
+  if (fd == kStdoutFd || fd == kStderrFd) return;
+  if (!full_path) return;
+
+  SpinMutexLock l(mu);
+  if (fd != kInvalidFd) CloseFile(fd);
+
+  fd = OpenFile(full_path, WrTrunc);
+}
+
 bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
                       uptr *read_len, uptr max_len, error_t *errno_p) {
   uptr PageSize = GetPageSizeCached();
Index: lib/sanitizer_common/sanitizer_flags.inc
===================================================================
--- lib/sanitizer_common/sanitizer_flags.inc
+++ lib/sanitizer_common/sanitizer_flags.inc
@@ -71,6 +71,10 @@
     "Invoke leak checking in an atexit handler. Has no effect if "
     "detect_leaks=false, or if __lsan_do_leak_check() is called before the "
     "handler has a chance to run.")
+COMMON_FLAG(uptr, leak_check_interval_s, 0,
+            "Experimental. If set, creates signal timer that performs "
+            "recoverable leak checking every leak_check_interval_s seconds. "
+            "Disabled if zero or detect_leaks=false.\n")
 COMMON_FLAG(bool, allocator_may_return_null, false,
             "If false, the allocator will crash instead of returning 0 on "
             "out-of-memory.")
Index: lib/sanitizer_common/sanitizer_linux.cc
===================================================================
--- lib/sanitizer_common/sanitizer_linux.cc
+++ lib/sanitizer_common/sanitizer_linux.cc
@@ -1700,12 +1700,55 @@
   return th;
 }
 
+static void *internal_timer_create(int signal, uptr interval_s) {
+  sigevent sev;
+  sev.sigev_notify = SIGEV_SIGNAL;
+  sev.sigev_signo = signal;
+  void *timer_id;
+  sev.sigev_value.sival_ptr = &timer_id;
+  CHECK_EQ(0, internal_syscall(SYSCALL(timer_create), CLOCK_REALTIME, &sev,
+                               &timer_id));
+  VPrintf(1, "Created timer for %d signal\n", signal, interval_s);
+  itimerspec its;
+  its.it_value.tv_sec = interval_s;
+  its.it_value.tv_nsec = 0;
+  its.it_interval.tv_sec = its.it_value.tv_sec;
+  its.it_interval.tv_nsec = 0;
+  CHECK_EQ(
+      0, internal_syscall(SYSCALL(timer_settime), timer_id, 0, &its, nullptr));
+  VPrintf(1, "Armed timer for %d signal, interval = %ul \n", signal,
+          interval_s);
+  return timer_id;
+}
+
+void *internal_start_signal_timer(SignalHandlerType handler, int signal,
+                                  uptr interval_s) {
+  __sanitizer_sigset_t set, old;
+  internal_sigfillset(&set);
+  internal_sigdelset(&set, signal);
+  CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &set, &old));
+  // Setting up sigaction
+  __sanitizer_sigaction sa;
+  internal_memset(&sa, 0, sizeof(sa));
+  sa.sa_flags = SA_SIGINFO | SA_RESTART;
+  sa.sigaction = (__sanitizer_sigactionhandler_ptr)(handler);
+  CHECK_EQ(0, internal_sigaction_syscall(signal, &sa, nullptr));
+  void *timer_id = internal_timer_create(signal, interval_s);
+  CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &old, nullptr));
+  return timer_id;
+}
+
 void internal_join_thread(void *th) {
   real_pthread_join(th, nullptr);
 }
 #else
 void *internal_start_thread(void (*func)(void *), void *arg) { return 0; }
 
+void *internal_start_signal_timer(SignalHandlerType handler, int signal,
+                                  uptr interval_s) {
+  return 0;
+}
+void *internal_timer_create(int signal, uptr interval_s) { return 0; }
 void internal_join_thread(void *th) {}
 #endif
 
Index: lib/sanitizer_common/sanitizer_posix.cc
===================================================================
--- lib/sanitizer_common/sanitizer_posix.cc
+++ lib/sanitizer_common/sanitizer_posix.cc
@@ -162,6 +162,7 @@
     case RdOnly: flags = O_RDONLY; break;
     case WrOnly: flags = O_WRONLY | O_CREAT; break;
     case RdWr: flags = O_RDWR | O_CREAT; break;
+    case WrTrunc: flags = O_WRONLY | O_CREAT | O_TRUNC; break;
   }
   fd_t res = internal_open(filename, flags, 0660);
   if (internal_iserror(res, errno_p))
Index: test/lsan/TestCases/Linux/leak_check_interval.cc
===================================================================
--- /dev/null
+++ test/lsan/TestCases/Linux/leak_check_interval.cc
@@ -0,0 +1,37 @@
+// Test for LSan background leak checking during application runtime
+// RUN: LSAN_BASE="use_stacks=0:use_registers=0"
+// RUN: %clangxx_lsan %s -o %t
+// RUN: LSAN_OPT="$LSAN_BASE:leak_check_interval_s=1:leak_check_at_exit=1"
+// RUN: %env_lsan_opts=$LSAN_BASE":leak_check_interval_s=1:leak_check_at_exit=1" not %run %t 2>&1 | FileCheck --check-prefix=CHECK-interval-exit %s
+// RUN: %env_lsan_opts=$LSAN_BASE":leak_check_interval_s=1:leak_check_at_exit=0" %run %t 2>&1 | FileCheck --check-prefix=CHECK-interval %s
+// RUN: %env_lsan_opts=$LSAN_BASE":leak_check_interval_s=0:leak_check_at_exit=1" not %run %t 2>&1 | FileCheck --check-prefix=CHECK-exit %s
+// RUN: %env_lsan_opts=$LSAN_BASE":leak_check_interval_s=0:leak_check_at_exit=0" %run %t 2>&1
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int Leak() {
+  volatile int *a = (int *)malloc(20);
+  a[0] = 1;
+  return a[0];
+}
+
+int main() {
+  Leak();
+  for (int i = 0; i < 3; ++i) {
+    sleep(1);
+  }
+  fprintf(stderr, "END_HERE\n");
+  return 0;
+}
+
+// CHECK-interval-exit: LeakSanitizer: detected memory leaks
+// CHECK-interval-exit: END_HERE
+// CHECK-interval-exit: LeakSanitizer: detected memory leaks
+
+// CHECK-interval: LeakSanitizer: detected memory leaks
+// CHECK-interval: END_HERE
+
+// CHECK-exit: END_HERE
+// CHECK-exit: LeakSanitizer: detected memory leaks