/*
 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/* @test
   @bug 4843136 4763384
   @summary Various race conditions caused exec'ed processes to have
   extra unused file descriptors, which caused hard-to-reproduce hangs.
   @author Martin Buchholz
*/

import java.util.Timer;
import java.util.TimerTask;
import java.io.IOException;

public class SleepyCat {

    private static void destroy (Process[] deathRow) {
        for (int i = 0; i < deathRow.length; ++i)
            if (deathRow[i] != null)
                deathRow[i].destroy();
    }

    static class TimeoutTask extends TimerTask {
        private Process[] deathRow;
        private boolean timedOut;

        TimeoutTask (Process[] deathRow) {
            this.deathRow = deathRow;
            this.timedOut = false;
        }

        public void run() {
            timedOut = true;
            destroy(deathRow);
        }

        public boolean timedOut() {
            return timedOut;
        }
    }

    private static boolean hang1() throws IOException, InterruptedException {
        // Time out was reproducible on Solaris 50% of the time;
        // on Linux 80% of the time.
        //
        // Scenario: After fork(), parent executes and closes write end of child's stdin.
        // This causes child to retain a write end of the same pipe.
        // Thus the child will never see an EOF on its stdin, and will hang.
        Runtime rt = Runtime.getRuntime();
        // Increasing the iteration count makes the bug more
        // reproducible not only for the obvious reason, but also for
        // the subtle reason that it makes reading /proc/getppid()/fd
        // slower, making the child more likely to win the race!
        int iterations = 20;
        int timeout = 30;
        String[] catArgs   = new String[] {"/bin/cat"};
        String[] sleepArgs = new String[] {"/bin/sleep",
                                            String.valueOf(timeout+1)};
        Process[] cats   = new Process[iterations];
        Process[] sleeps = new Process[iterations];
        Timer timer = new Timer(true);
        TimeoutTask catExecutioner = new TimeoutTask(cats);
        timer.schedule(catExecutioner, timeout * 1000);

        for (int i = 0; i < cats.length; ++i) {
            cats[i] = rt.exec(catArgs);
            java.io.OutputStream s = cats[i].getOutputStream();
            Process sleep = rt.exec(sleepArgs);
            s.close(); // race condition here
            sleeps[i] = sleep;
        }

        for (int i = 0; i < cats.length; ++i)
            cats[i].waitFor(); // hangs?

        timer.cancel();

        destroy(sleeps);

        if (catExecutioner.timedOut())
            System.out.println("Child process has a hidden writable pipe fd for its stdin.");
        return catExecutioner.timedOut();
    }

    private static boolean hang2() throws Exception {
        // Inspired by the imaginative test case for
        // 4850368 (process) getInputStream() attaches to forked background processes (Linux)

        // Time out was reproducible on Linux 80% of the time;
        // never on Solaris because of explicit close in Solaris-specific code.

        // Scenario: After fork(), the parent naturally closes the
        // child's stdout write end.  The child dup2's the write end
        // of its stdout onto fd 1.  On Linux, it fails to explicitly
        // close the original fd, and because of the parent's close()
        // of the fd, the child retains it.  The child thus ends up
        // with two copies of its stdout.  Thus closing one of those
        // write fds does not have the desired effect of causing an
        // EOF on the parent's read end of that pipe.
        Runtime rt = Runtime.getRuntime();
        int iterations = 10;
        Timer timer = new Timer(true);
        int timeout = 30;
        Process[] backgroundSleepers = new Process[iterations];
        TimeoutTask sleeperExecutioner = new TimeoutTask(backgroundSleepers);
        timer.schedule(sleeperExecutioner, timeout * 1000);
        byte[] buffer = new byte[10];
        String[] args =
            new String[] {"/bin/sh", "-c",
                          "exec sleep " + (timeout+1) + " >/dev/null"};

        for (int i = 0;
             i < backgroundSleepers.length && !sleeperExecutioner.timedOut();
             ++i) {
            backgroundSleepers[i] = rt.exec(args); // race condition here
            try {
                // should get immediate EOF, but might hang
                if (backgroundSleepers[i].getInputStream().read() != -1)
                    throw new Exception("Expected EOF, got a byte");
            } catch (IOException e) {
                // Stream closed by sleeperExecutioner
                break;
            }
        }

        timer.cancel();

        destroy(backgroundSleepers);

        if (sleeperExecutioner.timedOut())
            System.out.println("Child process has two (should be one) writable pipe fds for its stdout.");
        return sleeperExecutioner.timedOut();
    }

    public static void main (String[] args) throws Exception {
        try {
            if (hang1() | hang2())
                throw new Exception("Read from closed pipe hangs");
        } catch (IOException e) {
            // We will get here on non-Posix systems,
            // which don't have cat and sleep and sh.
        }
    }
}
