AI 145086: Use process groups to avoid a collision between dexopt and ProcessManager.
  If the ProcessManager thread was waiting for a child process to finish,
  it could inadvertently capture the exit status of dexopt.  This
  confused the VM somewhat.  With this change the dexopt child runs in
  its own process group, and the ProcessManager only waits for children
  in the parent's process group.
  I also now create a new process in the DexClassLoader test to check for
  clashes.  (It's a race, but it nearly always hits on the device, and
  occasionally hits on desktop.)
  BUG=1777736

Automated import of CL 145086
diff --git a/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c b/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c
index ee2fc58..a572237 100644
--- a/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c
+++ b/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c
@@ -91,7 +91,8 @@
     while (1) {
         int status;
 
-        pid_t pid = wait(&status);
+        /* wait for children in our process group */
+        pid_t pid = waitpid(0, &status, 0);
 
         if (pid >= 0) {
             // Extract real status.
diff --git a/tests/071-dexfile/src/Main.java b/tests/071-dexfile/src/Main.java
index 0e6cce7..42c841d 100644
--- a/tests/071-dexfile/src/Main.java
+++ b/tests/071-dexfile/src/Main.java
@@ -15,6 +15,7 @@
  */
 
 import java.io.File;
+import java.io.IOException;
 import java.lang.reflect.Constructor;
 
 /**
@@ -28,10 +29,49 @@
     private static final String LIB_DIR = "/nowhere/nothing/";
 
     /**
+     * Prep the environment then run the test.
+     */
+    public static void main(String[] args) {
+        Process p;
+        try {
+            /*
+             * Create a sub-process to see if the ProcessManager wait
+             * interferes with the dexopt invocation wait.
+             *
+             * /dev/random never hits EOF, so we're sure that we'll still
+             * be waiting for the process to complete.  On the device it
+             * stops pretty quickly (which means the child won't be
+             * spinning).
+             */
+            ProcessBuilder pb = new ProcessBuilder("cat", "/dev/random");
+            p = pb.start();
+        } catch (IOException ioe) {
+            System.err.println("cmd failed: " + ioe.getMessage());
+            p = null;
+        }
+
+        try {
+            testDexClassLoader();
+        } finally {
+            // shouldn't be necessary, but it's good to be tidy
+            if (p != null)
+                p.destroy();
+
+            // let the ProcessManager's daemon thread finish before we shut down
+            // (avoids the occasional segmentation fault)
+            try {
+                Thread.sleep(500);
+            } catch (Exception ex) {}
+        }
+
+        System.out.println("done");
+    }
+
+    /**
      * Create a class loader, explicitly specifying the source DEX and
      * the location for the optimized DEX.
      */
-    public static void main(String[] args) {
+    private static void testDexClassLoader() {
         ClassLoader dexClassLoader = getDexClassLoader();
 
         Class anotherClass;
@@ -50,10 +90,8 @@
             throw new RuntimeException("new another", ie);
         }
 
-        /* not expected to work; just exercises the call */
+        // not expected to work; just exercises the call
         dexClassLoader.getResource("nonexistent");
-
-        System.out.println("done");
     }
 
     /*
@@ -94,6 +132,7 @@
             throw new RuntimeException("DCL ctor", nsme);
         }
 
+        // create an instance, using the path we found
         Object dclObj;
         try {
             dclObj = ctor.newInstance(CLASS_PATH, odexDir, LIB_DIR, myLoader);
diff --git a/vm/analysis/DexOptimize.c b/vm/analysis/DexOptimize.c
index 70b3278..3ab6216 100644
--- a/vm/analysis/DexOptimize.c
+++ b/vm/analysis/DexOptimize.c
@@ -366,6 +366,9 @@
         char* androidRoot;
         int flags;
 
+        /* change process groups, so we don't clash with ProcessManager */
+        setpgid(0, 0);
+
         /* full path to optimizer */
         androidRoot = getenv("ANDROID_ROOT");
         if (androidRoot == NULL) {