Change when sampling thread is reset during shutdown to prevent races.

Also adds some extra argument checking and testing for tracing.

Bug: 17412385

(cherry picked from commit f8bdd4e783842577e49f418a0b5962ba49dfdd93)

Change-Id: Ifc4f1a296155d73255b29d264b5475024e6419da
diff --git a/runtime/trace.cc b/runtime/trace.cc
index ca5e150..6dcc5fe 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -334,8 +334,14 @@
       return;
     }
   }
-  Runtime* runtime = Runtime::Current();
-  runtime->GetThreadList()->SuspendAll();
+
+  // Check interval if sampling is enabled
+  if (sampling_enabled && interval_us <= 0) {
+    LOG(ERROR) << "Invalid sampling interval: " << interval_us;
+    ScopedObjectAccess soa(self);
+    ThrowRuntimeException("Invalid sampling interval: %d", interval_us);
+    return;
+  }
 
   // Open trace file if not going directly to ddms.
   std::unique_ptr<File> trace_file;
@@ -348,13 +354,15 @@
     }
     if (trace_file.get() == NULL) {
       PLOG(ERROR) << "Unable to open trace file '" << trace_filename << "'";
-      runtime->GetThreadList()->ResumeAll();
       ScopedObjectAccess soa(self);
       ThrowRuntimeException("Unable to open trace file '%s'", trace_filename);
       return;
     }
   }
 
+  Runtime* runtime = Runtime::Current();
+  runtime->GetThreadList()->SuspendAll();
+
   // Create Trace object.
   {
     MutexLock mu(self, *Locks::trace_lock_);
@@ -383,6 +391,7 @@
       }
     }
   }
+
   runtime->GetThreadList()->ResumeAll();
 }
 
@@ -399,7 +408,6 @@
       the_trace = the_trace_;
       the_trace_ = NULL;
       sampling_pthread = sampling_pthread_;
-      sampling_pthread_ = 0U;
     }
   }
   if (the_trace != NULL) {
@@ -421,6 +429,7 @@
 
   if (sampling_pthread != 0U) {
     CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, NULL), "sampling thread shutdown");
+    sampling_pthread_ = 0U;
   }
 }