c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync/* $Id$ */
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync/** @file
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync * VMM Fork Test.
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync */
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync/*
f7e6b78ab5390f576b42ba0648a4b82aef89731cvboxsync * Copyright (C) 2006-2014 Oracle Corporation
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync *
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync * available from http://www.virtualbox.org. This file is free software;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync */
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync/*******************************************************************************
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync* Header Files *
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync*******************************************************************************/
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/vmm/vm.h>
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/vmm/vmm.h>
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#include <VBox/err.h>
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#include <VBox/log.h>
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#include <iprt/assert.h>
5eabf773597082761832bc0a32b3660e8771f9f1vboxsync#include <iprt/initterm.h>
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#include <iprt/stream.h>
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#include <errno.h>
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#include <sys/wait.h>
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#include <unistd.h>
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync/*******************************************************************************
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync* Defined Constants And Macros *
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync*******************************************************************************/
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#define TESTCASE "tstVMMFork"
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#define AUTO_TEST_ARGS 1
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsyncVMMR3DECL(int) VMMDoTest(PVM pVM);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsyncint main(int argc, char* argv[])
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync{
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync int rcErrors = 0;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync /*
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync * Initialize the runtime.
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync */
230bd8589bba39933ac5ec21482d6186d675e604vboxsync RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#ifndef AUTO_TEST_ARGS
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync if (argc < 2)
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync {
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf("syntax: %s command [args]\n"
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync "\n"
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync "command Command to run under child process in fork.\n"
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync "[args] Arguments to command.\n", argv[0]);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync return 1;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync }
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#endif
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync /*
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync * Create empty VM.
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync */
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf(TESTCASE ": Initializing...\n");
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync PVM pVM;
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync PUVM pUVM;
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync int rc = VMR3Create(1, NULL, NULL, NULL, NULL, NULL, &pVM, &pUVM);
1a25adaca81841abf5e6cdfed02eaff64941357dvboxsync if (RT_SUCCESS(rc))
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync {
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync /*
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync * Do testing.
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync */
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync int iCowTester = 0;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync char cCowTester = 'a';
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#ifndef AUTO_TEST_ARGS
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync int cArgs = argc - 1;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync char **ppszArgs = &argv[1];
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#else
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync int cArgs = 2;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync char *ppszArgs[3];
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync ppszArgs[0] = (char *)"/bin/sleep";
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync ppszArgs[1] = (char *)"3";
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync ppszArgs[2] = NULL;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync#endif
dced478b440a327fb550155c0f73c1ac968ad93bvboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf(TESTCASE ": forking current process...\n");
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync pid_t pid = fork();
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync if (pid < 0)
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync {
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync /* Bad. fork() failed! */
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf(TESTCASE ": error: fork() failed.\n");
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync rcErrors++;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync }
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync else if (pid == 0)
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync {
dced478b440a327fb550155c0f73c1ac968ad93bvboxsync /*
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync * The child process.
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync * Write to some local variables to trigger copy-on-write if it's used.
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync */
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf(TESTCASE ": running child process...\n");
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf(TESTCASE ": writing local variables...\n");
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync iCowTester = 2;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync cCowTester = 'z';
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf(TESTCASE ": calling execv() with command-line:\n");
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync for (int i = 0; i < cArgs; i++)
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf(TESTCASE ": ppszArgs[%d]=%s\n", i, ppszArgs[i]);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync execv(ppszArgs[0], ppszArgs);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf(TESTCASE ": error: execv() returned to caller. errno=%d.\n", errno);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync _exit(-1);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync }
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync else
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync {
dced478b440a327fb550155c0f73c1ac968ad93bvboxsync /*
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync * The parent process.
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync * Wait for child & run VMM test to ensure things are fine.
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync */
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync int result;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync while (waitpid(pid, &result, 0) < 0)
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync ;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync if (!WIFEXITED(result) || WEXITSTATUS(result) != 0)
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync {
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf(TESTCASE ": error: failed to run child process. errno=%d\n", errno);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync rcErrors++;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync }
dced478b440a327fb550155c0f73c1ac968ad93bvboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync if (rcErrors == 0)
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync {
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf(TESTCASE ": fork() returned fine.\n");
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf(TESTCASE ": testing VM after fork.\n");
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)VMMDoTest, 1, pVM);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
a04100f955c08c93b063cf3d9c4f963637996f3cvboxsync STAMR3Dump(pUVM, "*");
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync }
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync }
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync if (rcErrors > 0)
f7e6b78ab5390f576b42ba0648a4b82aef89731cvboxsync RTPrintf(TESTCASE ": error: %d error(s) during fork(). Cannot proceed to test the VM.\n", rcErrors);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync else
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync RTPrintf(TESTCASE ": fork() and VM test, SUCCESS.\n");
dced478b440a327fb550155c0f73c1ac968ad93bvboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync /*
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync * Cleanup.
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync */
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync rc = VMR3PowerOff(pUVM);
a50f2b5d48e2f3f8bae70aa49f76f225352b67cdvboxsync if (!RT_SUCCESS(rc))
a50f2b5d48e2f3f8bae70aa49f76f225352b67cdvboxsync {
a50f2b5d48e2f3f8bae70aa49f76f225352b67cdvboxsync RTPrintf(TESTCASE ": error: failed to power off vm! rc=%Rrc\n", rc);
a50f2b5d48e2f3f8bae70aa49f76f225352b67cdvboxsync rcErrors++;
a50f2b5d48e2f3f8bae70aa49f76f225352b67cdvboxsync }
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync rc = VMR3Destroy(pUVM);
1a25adaca81841abf5e6cdfed02eaff64941357dvboxsync if (!RT_SUCCESS(rc))
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync {
a50f2b5d48e2f3f8bae70aa49f76f225352b67cdvboxsync RTPrintf(TESTCASE ": error: failed to destroy vm! rc=%Rrc\n", rc);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync rcErrors++;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync }
021c939a9e3f688c0c3bbd759354be906bb2dcabvboxsync VMR3ReleaseUVM(pUVM);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync }
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync else
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync {
a50f2b5d48e2f3f8bae70aa49f76f225352b67cdvboxsync RTPrintf(TESTCASE ": fatal error: failed to create vm! rc=%Rrc\n", rc);
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync rcErrors++;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync }
dced478b440a327fb550155c0f73c1ac968ad93bvboxsync
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync return rcErrors;
c189e41dcbb9bbda9b5bc41e07ef0fce82bbff7avboxsync}