<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Creator.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "maemoruncontrol.h"
#include "maemosshthread.h"
#include "maemorunconfiguration.h"

#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <debugger/debuggermanager.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/toolchain.h>
#include <utils/qtcassert.h>

#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QFuture>
#include <QtCore/QProcess>
#include <QtCore/QStringBuilder>

#include <QtGui/QMessageBox>

namespace Qt4ProjectManager {
namespace Internal {

using ProjectExplorer::RunConfiguration;
using ProjectExplorer::ToolChain;

AbstractMaemoRunControl::AbstractMaemoRunControl(RunConfiguration *rc)
    : RunControl(rc)
    , runConfig(qobject_cast<MaemoRunConfiguration *>(rc))
    , devConfig(runConfig ? runConfig->deviceConfig() : MaemoDeviceConfig())
{
}

AbstractMaemoRunControl::~AbstractMaemoRunControl()
{
}

void AbstractMaemoRunControl::startDeployment(bool forDebugging)
{
    QTC_ASSERT(runConfig, return);

    if (devConfig.isValid()) {
        deployables.clear();
        if (runConfig->currentlyNeedsDeployment(devConfig.host)) {
            deployables.append(Deployable(executableFileName(),
                QFileInfo(executableOnHost()).canonicalPath(),
                &MaemoRunConfiguration::wasDeployed));
        }
        if (forDebugging
            && runConfig->debuggingHelpersNeedDeployment(devConfig.host)) {
            const QFileInfo &info(runConfig->dumperLib());
            deployables.append(Deployable(info.fileName(), info.canonicalPath(),
                &MaemoRunConfiguration::debuggingHelpersDeployed));
        }

        deploy();
    } else {
        handleError(tr("No device configuration set for run configuration."));
        handleDeploymentFinished(false);
    }
}

void AbstractMaemoRunControl::deploy()
{
    Core::ICore::instance()->progressManager()
        ->addTask(m_progress.future(), tr("Deploying"),
                  QLatin1String("Maemo.Deploy"));
    if (!deployables.isEmpty()) {
        QList<SshDeploySpec> deploySpecs;
        QStringList files;
        foreach (const Deployable &deployable, deployables) {
            const QString srcFilePath
                = deployable.dir % QDir::separator() % deployable.fileName;
            const QString tgtFilePath
                = remoteDir() % QDir::separator() % deployable.fileName;
            files << srcFilePath;
            deploySpecs << SshDeploySpec(srcFilePath, tgtFilePath);
        }
        emit addToOutputWindow(this, tr("Files to deploy: %1.").arg(files.join(" ")));
        sshDeployer.reset(new MaemoSshDeployer(devConfig, deploySpecs));
        connect(sshDeployer.data(), SIGNAL(finished()),
                this, SLOT(deployProcessFinished()));
        connect(sshDeployer.data(), SIGNAL(fileCopied(QString)),
                this, SLOT(handleFileCopied()));
        m_progress.setProgressRange(0, deployables.count());
        m_progress.setProgressValue(0);
        m_progress.reportStarted();
        emit started();
        sshDeployer->start();
    } else {
        m_progress.reportFinished();
        handleDeploymentFinished(true);
    }
}

void AbstractMaemoRunControl::handleFileCopied()
{
    Deployable deployable = deployables.takeFirst();
    (runConfig->*deployable.updateTimestamp)(devConfig.host);
    m_progress.setProgressValue(m_progress.progressValue() + 1);
}

void AbstractMaemoRunControl::stopDeployment()
{
    sshDeployer->stop();
}

bool AbstractMaemoRunControl::isDeploying() const
{
    return !sshDeployer.isNull() && sshDeployer->isRunning();
}

void AbstractMaemoRunControl::deployProcessFinished()
{
    const bool success = !sshDeployer->hasError();
    if (success) {
        emit addToOutputWindow(this, tr("Deployment finished."));
    } else {
        handleError(tr("Deployment failed: %1").arg(sshDeployer->error()));
        m_progress.reportCanceled();
    }
    m_progress.reportFinished();
    handleDeploymentFinished(success);
}

const QString AbstractMaemoRunControl::executableOnHost() const
{
    qDebug("runconfig->executable: %s", qPrintable(runConfig->executable()));
    return runConfig->executable();
}

const QString AbstractMaemoRunControl::sshPort() const
{
    return devConfig.type == MaemoDeviceConfig::Physical
        ? QString::number(devConfig.sshPort)
        : runConfig->simulatorSshPort();
}

const QString AbstractMaemoRunControl::executableFileName() const
{
    return QFileInfo(executableOnHost()).fileName();
}

const QString AbstractMaemoRunControl::remoteDir() const
{
    return homeDirOnDevice(devConfig.uname);
}

const QStringList AbstractMaemoRunControl::options() const
{
    const bool usePassword
        = devConfig.authentication == MaemoDeviceConfig::Password;
    const QLatin1String opt("-o");
    QStringList optionList;
    if (!usePassword)
        optionList << QLatin1String("-i") << devConfig.keyFile;
    return optionList << opt
        << QString::fromLatin1("PasswordAuthentication=%1").
            arg(usePassword ? "yes" : "no") << opt
        << QString::fromLatin1("PubkeyAuthentication=%1").
            arg(usePassword ? "no" : "yes") << opt
        << QString::fromLatin1("ConnectTimeout=%1").arg(devConfig.timeout)
        << opt << QLatin1String("CheckHostIP=no")
        << opt << QLatin1String("StrictHostKeyChecking=no");
}

const QString AbstractMaemoRunControl::executableOnTarget() const
{
    return QString::fromLocal8Bit("%1/%2").arg(remoteDir()).
        arg(executableFileName());
}

const QString AbstractMaemoRunControl::targetCmdLinePrefix() const
{
    return QString::fromLocal8Bit("chmod u+x %1; source /etc/profile; ").
        arg(executableOnTarget());
}

void AbstractMaemoRunControl::handleError(const QString &errString)
{
    QMessageBox::critical(0, tr("Remote Execution Failure"), errString);
    emit error(this, errString);
}

MaemoRunControl::MaemoRunControl(RunConfiguration *runConfiguration)
    : AbstractMaemoRunControl(runConfiguration)
{
}

MaemoRunControl::~MaemoRunControl()
{
    stop();
}

void MaemoRunControl::start()
{
    stoppedByUser = false;
    startDeployment(false);
}

void MaemoRunControl::handleDeploymentFinished(bool success)
{
    if (success)
        startExecution();
    else
        emit finished();
}

void MaemoRunControl::startExecution()
{
    const QString remoteCall = QString::fromLocal8Bit("%1 %2 %3")
        .arg(targetCmdLinePrefix()).arg(executableOnTarget())
        .arg(runConfig->arguments().join(" "));
    sshRunner.reset(new MaemoSshRunner(devConfig, remoteCall));
    connect(sshRunner.data(), SIGNAL(remoteOutput(QString)),
            this, SLOT(handleRemoteOutput(QString)));
    connect(sshRunner.data(), SIGNAL(finished()),
            this, SLOT(executionFinished()));
    emit addToOutputWindow(this, tr("Starting remote application."));
    emit started();
    sshRunner->start();
}

void MaemoRunControl::executionFinished()
{
    if (stoppedByUser) {
        emit addToOutputWindow(this, tr("Remote process stopped by user."));
    } else if (sshRunner->hasError()) {
        emit addToOutputWindow(this, tr("Remote process exited with error: %1")
                                         .arg(sshRunner->error()));
    } else {
        emit addToOutputWindow(this, tr("Remote process finished successfully."));
    }
    emit finished();
}

void MaemoRunControl::stop()
{
    if (!isRunning())
        return;

    stoppedByUser = true;
    if (isDeploying()) {
        stopDeployment();
    } else {
        sshRunner->stop();
        const QString remoteCall = QString::fromLocal8Bit("pkill -x %1; "
            "sleep 1; pkill -x -9 %1").arg(executableFileName());
        sshStopper.reset(new MaemoSshRunner(devConfig, remoteCall));
        sshStopper->start();
    }
}

bool MaemoRunControl::isRunning() const
{
    return isDeploying()
        || (!sshRunner.isNull() && sshRunner->isRunning());
}

void MaemoRunControl::handleRemoteOutput(const QString &output)
{
    emit addToOutputWindowInline(this, output);
}

MaemoDebugRunControl::MaemoDebugRunControl(RunConfiguration *runConfiguration)
    : AbstractMaemoRunControl(runConfiguration)
    , debuggerManager(0)
    , startParams(new Debugger::DebuggerStartParameters)
{
    debuggerManager = ExtensionSystem::PluginManager::instance()
        ->getObject<Debugger::DebuggerManager>();

    QTC_ASSERT(debuggerManager != 0, return);
    startParams->startMode = Debugger::StartRemote;
    startParams->executable = executableOnHost();
    startParams->remoteChannel
        = devConfig.host % QLatin1Char(':') % gdbServerPort();
    startParams->remoteArchitecture = QLatin1String("arm");
    startParams->sysRoot = runConfig->sysRoot();
    startParams->toolChainType = ToolChain::GCC_MAEMO;
    startParams->debuggerCommand = runConfig->gdbCmd();
    startParams->dumperLibrary = runConfig->dumperLib();
    startParams->remoteDumperLib = QString::fromLocal8Bit("%1/%2")
        .arg(remoteDir()).arg(QFileInfo(runConfig->dumperLib()).fileName());

    connect(this, SIGNAL(stopRequested()), debuggerManager, SLOT(exitDebugger()));
    connect(debuggerManager, SIGNAL(debuggingFinished()), this,
        SLOT(debuggingFinished()), Qt::QueuedConnection);
    connect(debuggerManager, SIGNAL(applicationOutputAvailable(QString)),
        this, SLOT(debuggerOutput(QString)), Qt::QueuedConnection);
}

MaemoDebugRunControl::~MaemoDebugRunControl()
{
    disconnect(SIGNAL(addToOutputWindow(RunControl*,QString)));
    disconnect(SIGNAL(addToOutputWindowInline(RunControl*,QString)));
    stop();
    debuggingFinished();
}

void MaemoDebugRunControl::start()
{
    startDeployment(true);
}

void MaemoDebugRunControl::handleDeploymentFinished(bool success)
{
    if (success) {
        startGdbServer();
    } else {
        emit finished();
    }
}

void MaemoDebugRunControl::startGdbServer()
{
    const QString remoteCall(QString::fromLocal8Bit("%1 gdbserver :%2 %3 %4").
        arg(targetCmdLinePrefix()).arg(gdbServerPort())
        .arg(executableOnTarget()).arg(runConfig->arguments().join(" ")));
    inferiorPid = -1;
    sshRunner.reset(new MaemoSshRunner(devConfig, remoteCall));
    connect(sshRunner.data(), SIGNAL(remoteOutput(QString)),
            this, SLOT(gdbServerStarted(QString)));
    sshRunner->start();
}

void MaemoDebugRunControl::gdbServerStartFailed(const QString &reason)
{
    handleError(tr("Debugging failed: %1").arg(reason));
    emit stopRequested();
    emit finished();
}

void MaemoDebugRunControl::gdbServerStarted(const QString &output)
{
    qDebug("gdbserver's stderr output: %s", output.toLatin1().data());
    if (inferiorPid != -1)
        return;
    const QString searchString("pid = ");
    const int searchStringLength = searchString.length();
    int pidStartPos = output.indexOf(searchString);
    const int pidEndPos = output.indexOf("\n", pidStartPos + searchStringLength);
    if (pidStartPos == -1 || pidEndPos == -1) {
        gdbServerStartFailed(output);
        return;
    }
    pidStartPos += searchStringLength;
    QString pidString = output.mid(pidStartPos, pidEndPos - pidStartPos);
    qDebug("pidString = %s", pidString.toLatin1().data());
    bool ok;
    const int pid = pidString.toInt(&ok);
    if (!ok) {
        gdbServerStartFailed(tr("Debugging failed, could not parse gdb "
            "server pid!"));
        return;
    }
    inferiorPid = pid;
    qDebug("inferiorPid = %d", inferiorPid);

    disconnect(sshRunner.data(), SIGNAL(remoteOutput(QString)), 0, 0);
    startDebugging();
}

void MaemoDebugRunControl::startDebugging()
{
    debuggerManager->startNewDebugger(startParams);
}

void MaemoDebugRunControl::stop()
{
    if (!isRunning())
        return;
    emit addToOutputWindow(this, tr("Stopping debugging operation ..."));
    if (isDeploying()) {
        stopDeployment();
    } else {
        emit stopRequested();
    }
}

bool MaemoDebugRunControl::isRunning() const
{
    return isDeploying()
        || (!sshRunner.isNull() && sshRunner->isRunning())
        || debuggerManager->state() != Debugger::DebuggerNotReady;
}

void MaemoDebugRunControl::debuggingFinished()
{
    if (!sshRunner.isNull() && sshRunner->isRunning()) {
        sshRunner->stop();
        const QString remoteCall = QString::fromLocal8Bit("kill %1; sleep 1; "
            "kill -9 %1; pkill -x -9 gdbserver").arg(inferiorPid);
        sshStopper.reset(new MaemoSshRunner(devConfig, remoteCall));
        sshStopper->start();
    }
    emit addToOutputWindow(this, tr("Debugging finished."));
    emit finished();
}

void MaemoDebugRunControl::debuggerOutput(const QString &output)
{
    emit addToOutputWindowInline(this, output);
}

QString MaemoDebugRunControl::gdbServerPort() const
{
    return devConfig.type == MaemoDeviceConfig::Physical
        ? QString::number(devConfig.gdbServerPort)
        : runConfig->simulatorGdbServerPort();
}

} // namespace Internal
} // namespace Qt4ProjectManager
<commit_msg>Maemo: Refactor running, debugging and stopping<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Creator.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "maemoruncontrol.h"
#include "maemosshthread.h"
#include "maemorunconfiguration.h"

#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <debugger/debuggermanager.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/toolchain.h>
#include <utils/qtcassert.h>

#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QFuture>
#include <QtCore/QProcess>
#include <QtCore/QStringBuilder>

#include <QtGui/QMessageBox>

namespace Qt4ProjectManager {
namespace Internal {

using ProjectExplorer::RunConfiguration;
using ProjectExplorer::ToolChain;

AbstractMaemoRunControl::AbstractMaemoRunControl(RunConfiguration *rc)
    : RunControl(rc)
    , runConfig(qobject_cast<MaemoRunConfiguration *>(rc))
    , devConfig(runConfig ? runConfig->deviceConfig() : MaemoDeviceConfig())
{
}

AbstractMaemoRunControl::~AbstractMaemoRunControl()
{
}

void AbstractMaemoRunControl::startDeployment(bool forDebugging)
{
    QTC_ASSERT(runConfig, return);

    if (devConfig.isValid()) {
        deployables.clear();
        if (runConfig->currentlyNeedsDeployment(devConfig.host)) {
            deployables.append(Deployable(executableFileName(),
                QFileInfo(executableOnHost()).canonicalPath(),
                &MaemoRunConfiguration::wasDeployed));
        }
        if (forDebugging
            && runConfig->debuggingHelpersNeedDeployment(devConfig.host)) {
            const QFileInfo &info(runConfig->dumperLib());
            deployables.append(Deployable(info.fileName(), info.canonicalPath(),
                &MaemoRunConfiguration::debuggingHelpersDeployed));
        }

        deploy();
    } else {
        handleError(tr("No device configuration set for run configuration."));
        handleDeploymentFinished(false);
    }
}

void AbstractMaemoRunControl::deploy()
{
    Core::ICore::instance()->progressManager()
        ->addTask(m_progress.future(), tr("Deploying"),
                  QLatin1String("Maemo.Deploy"));
    if (!deployables.isEmpty()) {
        QList<SshDeploySpec> deploySpecs;
        QStringList files;
        foreach (const Deployable &deployable, deployables) {
            const QString srcFilePath
                = deployable.dir % QDir::separator() % deployable.fileName;
            const QString tgtFilePath
                = remoteDir() % QDir::separator() % deployable.fileName;
            files << srcFilePath;
            deploySpecs << SshDeploySpec(srcFilePath, tgtFilePath);
        }
        emit addToOutputWindow(this, tr("Files to deploy: %1.").arg(files.join(" ")));
        sshDeployer.reset(new MaemoSshDeployer(devConfig, deploySpecs));
        connect(sshDeployer.data(), SIGNAL(finished()),
                this, SLOT(deployProcessFinished()));
        connect(sshDeployer.data(), SIGNAL(fileCopied(QString)),
                this, SLOT(handleFileCopied()));
        m_progress.setProgressRange(0, deployables.count());
        m_progress.setProgressValue(0);
        m_progress.reportStarted();
        emit started();
        sshDeployer->start();
    } else {
        m_progress.reportFinished();
        handleDeploymentFinished(true);
    }
}

void AbstractMaemoRunControl::handleFileCopied()
{
    Deployable deployable = deployables.takeFirst();
    (runConfig->*deployable.updateTimestamp)(devConfig.host);
    m_progress.setProgressValue(m_progress.progressValue() + 1);
}

void AbstractMaemoRunControl::stopDeployment()
{
    sshDeployer->stop();
}

bool AbstractMaemoRunControl::isDeploying() const
{
    return sshDeployer && sshDeployer->isRunning();
}

void AbstractMaemoRunControl::run(const QString &remoteCall)
{
    sshRunner.reset(new MaemoSshRunner(devConfig, remoteCall));
    handleExecutionAboutToStart(sshRunner.data());
    sshRunner->start();
}

bool AbstractMaemoRunControl::isRunning() const
{
    return isDeploying() || (sshRunner && sshRunner->isRunning());
}

void AbstractMaemoRunControl::stopRunning(bool forDebugging)
{
    if (sshRunner && sshRunner->isRunning()) {
        sshRunner->stop();
        QStringList apps(executableFileName());
        if (forDebugging)
            apps << QLatin1String("gdbserver");
        kill(apps);
    }
}

void AbstractMaemoRunControl::kill(const QStringList &apps)
{
    QString niceKill;
    QString brutalKill;
    foreach (const QString &app, apps) {
        niceKill += QString::fromLocal8Bit("pkill -x %1;").arg(app);
        brutalKill += QString::fromLocal8Bit("pkill -x -9 %1;").arg(app);
    }
    const QString remoteCall
        = niceKill + QLatin1String("sleep 1; ") + brutalKill;
    sshStopper.reset(new MaemoSshRunner(devConfig, remoteCall));
    sshStopper->start();
}

void AbstractMaemoRunControl::deployProcessFinished()
{
    const bool success = !sshDeployer->hasError();
    if (success) {
        emit addToOutputWindow(this, tr("Deployment finished."));
    } else {
        handleError(tr("Deployment failed: %1").arg(sshDeployer->error()));
        m_progress.reportCanceled();
    }
    m_progress.reportFinished();
    handleDeploymentFinished(success);
}

const QString AbstractMaemoRunControl::executableOnHost() const
{
    qDebug("runconfig->executable: %s", qPrintable(runConfig->executable()));
    return runConfig->executable();
}

const QString AbstractMaemoRunControl::sshPort() const
{
    return devConfig.type == MaemoDeviceConfig::Physical
        ? QString::number(devConfig.sshPort)
        : runConfig->simulatorSshPort();
}

const QString AbstractMaemoRunControl::executableFileName() const
{
    return QFileInfo(executableOnHost()).fileName();
}

const QString AbstractMaemoRunControl::remoteDir() const
{
    return homeDirOnDevice(devConfig.uname);
}

const QStringList AbstractMaemoRunControl::options() const
{
    const bool usePassword
        = devConfig.authentication == MaemoDeviceConfig::Password;
    const QLatin1String opt("-o");
    QStringList optionList;
    if (!usePassword)
        optionList << QLatin1String("-i") << devConfig.keyFile;
    return optionList << opt
        << QString::fromLatin1("PasswordAuthentication=%1").
            arg(usePassword ? "yes" : "no") << opt
        << QString::fromLatin1("PubkeyAuthentication=%1").
            arg(usePassword ? "no" : "yes") << opt
        << QString::fromLatin1("ConnectTimeout=%1").arg(devConfig.timeout)
        << opt << QLatin1String("CheckHostIP=no")
        << opt << QLatin1String("StrictHostKeyChecking=no");
}

const QString AbstractMaemoRunControl::executableOnTarget() const
{
    return QString::fromLocal8Bit("%1/%2").arg(remoteDir()).
        arg(executableFileName());
}

const QString AbstractMaemoRunControl::targetCmdLinePrefix() const
{
    return QString::fromLocal8Bit("chmod u+x %1; source /etc/profile; ").
        arg(executableOnTarget());
}

void AbstractMaemoRunControl::handleError(const QString &errString)
{
    QMessageBox::critical(0, tr("Remote Execution Failure"), errString);
    emit error(this, errString);
}

MaemoRunControl::MaemoRunControl(RunConfiguration *runConfiguration)
    : AbstractMaemoRunControl(runConfiguration)
{
}

MaemoRunControl::~MaemoRunControl()
{
    stop();
}

void MaemoRunControl::start()
{
    stoppedByUser = false;
    startDeployment(false);
}

void MaemoRunControl::handleDeploymentFinished(bool success)
{
    if (success)
        startExecution();
    else
        emit finished();
}

void MaemoRunControl::handleExecutionAboutToStart(const MaemoSshRunner *runner)
{
    connect(runner, SIGNAL(remoteOutput(QString)),
            this, SLOT(handleRemoteOutput(QString)));
    connect(runner, SIGNAL(finished()),
            this, SLOT(executionFinished()));
    emit addToOutputWindow(this, tr("Starting remote application."));
    emit started();
}

void MaemoRunControl::startExecution()
{
    const QString remoteCall = QString::fromLocal8Bit("%1 %2 %3")
        .arg(targetCmdLinePrefix()).arg(executableOnTarget())
        .arg(runConfig->arguments().join(" "));
    run(remoteCall);
}

void MaemoRunControl::executionFinished()
{
    MaemoSshRunner *runner = static_cast<MaemoSshRunner *>(sender());
    if (stoppedByUser) {
        emit addToOutputWindow(this, tr("Remote process stopped by user."));
    } else if (runner->hasError()) {
        emit addToOutputWindow(this, tr("Remote process exited with error: %1")
                                         .arg(runner->error()));
    } else {
        emit addToOutputWindow(this, tr("Remote process finished successfully."));
    }
    emit finished();
}

void MaemoRunControl::stop()
{
    if (!isRunning())
        return;

    stoppedByUser = true;
    if (isDeploying()) {
        stopDeployment();
    } else {
        AbstractMaemoRunControl::stopRunning(false);
    }
}

void MaemoRunControl::handleRemoteOutput(const QString &output)
{
    emit addToOutputWindowInline(this, output);
}

MaemoDebugRunControl::MaemoDebugRunControl(RunConfiguration *runConfiguration)
    : AbstractMaemoRunControl(runConfiguration)
    , debuggerManager(0)
    , startParams(new Debugger::DebuggerStartParameters)
{
    debuggerManager = ExtensionSystem::PluginManager::instance()
        ->getObject<Debugger::DebuggerManager>();

    QTC_ASSERT(debuggerManager != 0, return);
    startParams->startMode = Debugger::StartRemote;
    startParams->executable = executableOnHost();
    startParams->remoteChannel
        = devConfig.host % QLatin1Char(':') % gdbServerPort();
    startParams->remoteArchitecture = QLatin1String("arm");
    startParams->sysRoot = runConfig->sysRoot();
    startParams->toolChainType = ToolChain::GCC_MAEMO;
    startParams->debuggerCommand = runConfig->gdbCmd();
    startParams->dumperLibrary = runConfig->dumperLib();
    startParams->remoteDumperLib = QString::fromLocal8Bit("%1/%2")
        .arg(remoteDir()).arg(QFileInfo(runConfig->dumperLib()).fileName());

    connect(this, SIGNAL(stopRequested()), debuggerManager, SLOT(exitDebugger()));
    connect(debuggerManager, SIGNAL(debuggingFinished()), this,
        SLOT(debuggingFinished()), Qt::QueuedConnection);
    connect(debuggerManager, SIGNAL(applicationOutputAvailable(QString)),
        this, SLOT(debuggerOutput(QString)), Qt::QueuedConnection);
}

MaemoDebugRunControl::~MaemoDebugRunControl()
{
    disconnect(SIGNAL(addToOutputWindow(RunControl*,QString)));
    disconnect(SIGNAL(addToOutputWindowInline(RunControl*,QString)));
    stop();
    debuggingFinished();
}

void MaemoDebugRunControl::start()
{
    startDeployment(true);
}

void MaemoDebugRunControl::handleDeploymentFinished(bool success)
{
    if (success) {
        startGdbServer();
    } else {
        emit finished();
    }
}

void MaemoDebugRunControl::handleExecutionAboutToStart(const MaemoSshRunner *runner)
{
    inferiorPid = -1;
    connect(runner, SIGNAL(remoteOutput(QString)),
            this, SLOT(gdbServerStarted(QString)));
}

void MaemoDebugRunControl::startGdbServer()
{
    const QString remoteCall(QString::fromLocal8Bit("%1 gdbserver :%2 %3 %4").
        arg(targetCmdLinePrefix()).arg(gdbServerPort())
        .arg(executableOnTarget()).arg(runConfig->arguments().join(" ")));
    run(remoteCall);
}

void MaemoDebugRunControl::gdbServerStartFailed(const QString &reason)
{
    handleError(tr("Debugging failed: %1").arg(reason));
    emit stopRequested();
    emit finished();
}

void MaemoDebugRunControl::gdbServerStarted(const QString &output)
{
    qDebug("gdbserver's stderr output: %s", output.toLatin1().data());
    if (inferiorPid != -1)
        return;
    const QString searchString("pid = ");
    const int searchStringLength = searchString.length();
    int pidStartPos = output.indexOf(searchString);
    const int pidEndPos = output.indexOf("\n", pidStartPos + searchStringLength);
    if (pidStartPos == -1 || pidEndPos == -1) {
        gdbServerStartFailed(output);
        return;
    }
    pidStartPos += searchStringLength;
    QString pidString = output.mid(pidStartPos, pidEndPos - pidStartPos);
    qDebug("pidString = %s", pidString.toLatin1().data());
    bool ok;
    const int pid = pidString.toInt(&ok);
    if (!ok) {
        gdbServerStartFailed(tr("Debugging failed, could not parse gdb "
            "server pid!"));
        return;
    }
    inferiorPid = pid;
    qDebug("inferiorPid = %d", inferiorPid);

    startDebugging();
}

void MaemoDebugRunControl::startDebugging()
{
    debuggerManager->startNewDebugger(startParams);
}

void MaemoDebugRunControl::stop()
{
    if (!isRunning())
        return;
    emit addToOutputWindow(this, tr("Stopping debugging operation ..."));
    if (isDeploying()) {
        stopDeployment();
    } else {
        emit stopRequested();
    }
}

bool MaemoDebugRunControl::isRunning() const
{
    return AbstractMaemoRunControl::isRunning()
        || debuggerManager->state() != Debugger::DebuggerNotReady;
}

void MaemoDebugRunControl::debuggingFinished()
{
    AbstractMaemoRunControl::stopRunning(true);
    emit addToOutputWindow(this, tr("Debugging finished."));
    emit finished();
}

void MaemoDebugRunControl::debuggerOutput(const QString &output)
{
    emit addToOutputWindowInline(this, output);
}

QString MaemoDebugRunControl::gdbServerPort() const
{
    return devConfig.type == MaemoDeviceConfig::Physical
        ? QString::number(devConfig.gdbServerPort)
        : runConfig->simulatorGdbServerPort();
}

} // namespace Internal
} // namespace Qt4ProjectManager
<|endoftext|>


<commit_before>//===-- shm.cpp -----------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Save/restore via shared memory to survive exec*()
//
//===----------------------------------------------------------------------===//

#include "shm.h"

#include "ipcreg_internal.h"
#include "magic_socket_nums.h"
#include "real.h"
#include "rename_fd.h"

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

static char buf[100];
const char *getShmName() {
  sprintf(buf, "/ipcd.%d\n", getpid());
  return buf;
}

int get_shm(int flags, mode_t mode) {
  int fd = shm_open(getShmName(), flags, mode);
  if (fd != -1) {
    int ret = fchmod(fd, mode);
    if (ret == -1) {
      ipclog("Failure setting shared memory permissions: %s\n", strerror(errno));
    }
  }
  return fd;
}

void shm_state_save() {
  // Create shared memory segment
  int fd = get_shm(O_RDWR | O_CREAT | O_EXCL, 0600);
  assert(fd != -1);

  bool success = rename_fd(fd, MAGIC_SHM_FD, /* cloexec */ false);
  assert(success && "Failed to rename SHM fd!");

  // Do *not* close on exec! :)
  int flags = __real_fcntl(MAGIC_SHM_FD, F_GETFD, /* kludge */ 0);
  assert(flags >= 0);
  flags &= ~FD_CLOEXEC;
  int ret = __real_fcntl_int(MAGIC_SHM_FD, F_SETFD, flags);
  assert(ret != -1);

  // Size the memory segment:
  ret = ftruncate(MAGIC_SHM_FD, sizeof(libipc_state));
  assert(ret != -1);

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                  MAP_SHARED, MAGIC_SHM_FD, 0);
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  *(libipc_state*)stateptr = state;

  // Unmap, but don't unlink the shared memory
  ret = munmap(stateptr, sizeof(libipc_state));
  assert(ret != -1);

  ipclog("State saved!\n");
}

bool is_valid_fd(int fd) {
  return __real_fcntl(fd, F_GETFD, /* kludge */ 0) >= 0;
}

void shm_state_restore() {
  // If we have memory to restore, it'll be in our magic FD!
  if (!is_valid_fd(MAGIC_SHM_FD))
    return;

  ipclog("Inherited ipc state FD, starting state restoration...\n");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                        MAP_SHARED, MAGIC_SHM_FD, 0);
  // If our FD is still open, the memory better still be there!
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  // Copy state from shared memory segment
  state = *(libipc_state*)stateptr;

  int ret = munmap(stateptr, sizeof(libipc_state));
  assert(ret != -1);

  // Done with the shared segment, thank you!
  ret = __real_close(MAGIC_SHM_FD);
  assert(ret != -1);
  ret = shm_unlink(getShmName());
  assert(ret != -1);

  ipclog("State restored!\n");
}

void shm_state_destroy() {
  // If we have memory to restore, it'll be in our magic FD!
  assert(is_valid_fd(MAGIC_SHM_FD));

  int ret = __real_close(MAGIC_SHM_FD);
  assert(ret == 0);

  ret = shm_unlink(getShmName());
  assert(ret != -1);

  ipclog("Destroyed saved state!\n");
}
<commit_msg>libipc: Add more verbose/handy checking of unix calls, for debugging.<commit_after>//===-- shm.cpp -----------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Save/restore via shared memory to survive exec*()
//
//===----------------------------------------------------------------------===//

#include "shm.h"

#include "ipcreg_internal.h"
#include "magic_socket_nums.h"
#include "real.h"
#include "rename_fd.h"

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#define UC(ret, msg) \
  unixCheck(ret, msg, __FILE__, __LINE__, __PRETTY_FUNCTION__);

void unixCheck(int ret, const char *msg, const char *file, unsigned line,
               const char *func, int err = errno) {
  if (ret == -1) {
    ipclog("Unix call failed in %s at %s:%u: %s - %s\n", func, file, line, msg,
           strerror(err));
    abort();
  }
}

static char buf[100];
const char *getShmName() {
  sprintf(buf, "/ipcd.%d\n", getpid());
  return buf;
}

int get_shm(int flags, mode_t mode) {
  int fd = shm_open(getShmName(), flags, mode);
  UC(fd, "shm_open");
  UC(fchmod(fd, mode), "fchmod on shared memory segment");
  return fd;
}

void shm_state_save() {
  // Create shared memory segment
  int fd = get_shm(O_RDWR | O_CREAT | O_EXCL, 0600);
  UC(fd, "get_shm");

  bool success = rename_fd(fd, MAGIC_SHM_FD, /* cloexec */ false);
  assert(success && "Failed to rename SHM fd!");

  // Do *not* close on exec! :)
  int flags = __real_fcntl(MAGIC_SHM_FD, F_GETFD, /* kludge */ 0);
  assert(flags >= 0);
  flags &= ~FD_CLOEXEC;
  int ret = __real_fcntl_int(MAGIC_SHM_FD, F_SETFD, flags);
  UC(ret, "fcntl CLOEXEC on shared memory segment");

  // Size the memory segment:
  ret = ftruncate(MAGIC_SHM_FD, sizeof(libipc_state));
  UC(ret, "ftruncate on shm");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                  MAP_SHARED, MAGIC_SHM_FD, 0);
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  *(libipc_state*)stateptr = state;

  // Unmap, but don't unlink the shared memory
  ret = munmap(stateptr, sizeof(libipc_state));
  UC(ret, "unmap shm");

  ipclog("State saved!\n");
}

bool is_valid_fd(int fd) {
  return __real_fcntl(fd, F_GETFD, /* kludge */ 0) >= 0;
}

void shm_state_restore() {
  // If we have memory to restore, it'll be in our magic FD!
  if (!is_valid_fd(MAGIC_SHM_FD))
    return;

  ipclog("Inherited ipc state FD, starting state restoration...\n");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                        MAP_SHARED, MAGIC_SHM_FD, 0);
  // If our FD is still open, the memory better still be there!
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  // Copy state from shared memory segment
  state = *(libipc_state*)stateptr;

  int ret = munmap(stateptr, sizeof(libipc_state));
  UC(ret, "unmap shm");

  // Done with the shared segment, thank you!
  ret = __real_close(MAGIC_SHM_FD);
  UC(ret, "close shm");
  ret = shm_unlink(getShmName());
  UC(ret, "shm_unlink after close");

  ipclog("State restored!\n");
}

void shm_state_destroy() {
  // If we have memory to restore, it'll be in our magic FD!
  assert(is_valid_fd(MAGIC_SHM_FD));

  int ret = __real_close(MAGIC_SHM_FD);
  assert(ret == 0);

  ret = shm_unlink(getShmName());
  UC(ret, "shm_unlink");

  ipclog("Destroyed saved state!\n");
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2019 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <seastar/core/do_with.hh>
#include <seastar/util/noncopyable_function.hh>
#include <seastar/core/sharded.hh>
#include <seastar/util/defer.hh>

#include "sstables/sstables.hh"
#include "test/lib/tmpdir.hh"
#include "test/lib/test_services.hh"

namespace sstables {

class test_env {
    sstables_manager& _mgr;
public:
    explicit test_env() : _mgr(test_sstables_manager) { }
    explicit test_env(sstables_manager& mgr) : _mgr(mgr) { }

    future<> stop() {
        return make_ready_future<>();
    }

    shared_sstable make_sstable(schema_ptr schema, sstring dir, unsigned long generation,
            sstable::version_types v, sstable::format_types f = sstable::format_types::big,
            size_t buffer_size = default_sstable_buffer_size, gc_clock::time_point now = gc_clock::now()) {
        return _mgr.make_sstable(std::move(schema), dir, generation, v, f, now, default_io_error_handler_gen(), buffer_size);
    }

    future<shared_sstable> reusable_sst(schema_ptr schema, sstring dir, unsigned long generation,
            sstable::version_types version = sstable::version_types::la, sstable::format_types f = sstable::format_types::big) {
        auto sst = make_sstable(std::move(schema), dir, generation, version, f);
        return sst->load().then([sst = std::move(sst)] {
            return make_ready_future<shared_sstable>(std::move(sst));
        });
    }

    sstables_manager& manager() { return _mgr; }

    future<> working_sst(schema_ptr schema, sstring dir, unsigned long generation) {
        return reusable_sst(std::move(schema), dir, generation).then([] (auto ptr) { return make_ready_future<>(); });
    }

    template <typename Func>
    static inline auto do_with(Func&& func) {
        return seastar::do_with(test_env(), [func = std::move(func)] (test_env& env) mutable {
            return func(env);
        });
    }

    template <typename T, typename Func>
    static inline auto do_with(T&& rval, Func&& func) {
        return seastar::do_with(test_env(), std::forward<T>(rval), [func = std::move(func)] (test_env& env, T& val) mutable {
            return func(env, val);
        });
    }

    static inline future<> do_with_async(noncopyable_function<void (test_env&)> func) {
        return seastar::async([func = std::move(func)] {
            auto wait_for_background_jobs = defer([] { sstables::await_background_jobs_on_all_shards().get(); });
            test_env env;
            func(env);
        });
    }

    static inline future<> do_with_sharded_async(noncopyable_function<void (sharded<test_env>&)> func) {
        return seastar::async([func = std::move(func)] {
            auto wait_for_background_jobs = defer([] { sstables::await_background_jobs_on_all_shards().get(); });
            sharded<test_env> env;
            env.start().get();
            auto stop = defer([&] { env.stop().get(); });
            func(env);
        });
    }

    template <typename T>
    static future<T> do_with_async_returning(noncopyable_function<T (test_env&)> func) {
        return seastar::async([func = std::move(func)] {
            auto wait_for_background_jobs = defer([] { sstables::await_background_jobs_on_all_shards().get(); });
            test_env env;
            auto stop = defer([&] { env.stop().get(); });
            return func(env);
        });
    }
};

}   // namespace sstables
<commit_msg>test: sstables::test_env: close self in do_with helpers<commit_after>/*
 * Copyright (C) 2019 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <seastar/core/do_with.hh>
#include <seastar/util/noncopyable_function.hh>
#include <seastar/core/sharded.hh>
#include <seastar/util/defer.hh>

#include "sstables/sstables.hh"
#include "test/lib/tmpdir.hh"
#include "test/lib/test_services.hh"

namespace sstables {

class test_env {
    sstables_manager& _mgr;
public:
    explicit test_env() : _mgr(test_sstables_manager) { }
    explicit test_env(sstables_manager& mgr) : _mgr(mgr) { }

    future<> stop() {
        return make_ready_future<>();
    }

    shared_sstable make_sstable(schema_ptr schema, sstring dir, unsigned long generation,
            sstable::version_types v, sstable::format_types f = sstable::format_types::big,
            size_t buffer_size = default_sstable_buffer_size, gc_clock::time_point now = gc_clock::now()) {
        return _mgr.make_sstable(std::move(schema), dir, generation, v, f, now, default_io_error_handler_gen(), buffer_size);
    }

    future<shared_sstable> reusable_sst(schema_ptr schema, sstring dir, unsigned long generation,
            sstable::version_types version = sstable::version_types::la, sstable::format_types f = sstable::format_types::big) {
        auto sst = make_sstable(std::move(schema), dir, generation, version, f);
        return sst->load().then([sst = std::move(sst)] {
            return make_ready_future<shared_sstable>(std::move(sst));
        });
    }

    sstables_manager& manager() { return _mgr; }

    future<> working_sst(schema_ptr schema, sstring dir, unsigned long generation) {
        return reusable_sst(std::move(schema), dir, generation).then([] (auto ptr) { return make_ready_future<>(); });
    }

    template <typename Func>
    static inline auto do_with(Func&& func) {
        return seastar::do_with(test_env(), [func = std::move(func)] (test_env& env) mutable {
            return func(env).finally([&env] {
                return env.stop();
            });
        });
    }

    template <typename T, typename Func>
    static inline auto do_with(T&& rval, Func&& func) {
        return seastar::do_with(test_env(), std::forward<T>(rval), [func = std::move(func)] (test_env& env, T& val) mutable {
            return func(env, val).finally([&env] {
                return env.stop();
            });
        });
    }

    static inline future<> do_with_async(noncopyable_function<void (test_env&)> func) {
        return seastar::async([func = std::move(func)] {
            auto wait_for_background_jobs = defer([] { sstables::await_background_jobs_on_all_shards().get(); });
            test_env env;
            auto close_env = defer([&] { env.stop().get(); });
            func(env);
        });
    }

    static inline future<> do_with_sharded_async(noncopyable_function<void (sharded<test_env>&)> func) {
        return seastar::async([func = std::move(func)] {
            auto wait_for_background_jobs = defer([] { sstables::await_background_jobs_on_all_shards().get(); });
            sharded<test_env> env;
            env.start().get();
            auto stop = defer([&] { env.stop().get(); });
            func(env);
        });
    }

    template <typename T>
    static future<T> do_with_async_returning(noncopyable_function<T (test_env&)> func) {
        return seastar::async([func = std::move(func)] {
            auto wait_for_background_jobs = defer([] { sstables::await_background_jobs_on_all_shards().get(); });
            test_env env;
            auto stop = defer([&] { env.stop().get(); });
            return func(env);
        });
    }
};

}   // namespace sstables
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/installer/util/wmi.h"

#include <windows.h>

#include "base/basictypes.h"
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_variant.h"

#pragma comment(lib, "wbemuuid.lib")

namespace installer {

namespace {

// Simple class to manage the lifetime of a variant.
// TODO(tommi): Replace this for a more useful class.
class VariantHelper : public VARIANT {
 public:
  VariantHelper() {
    vt = VT_EMPTY;
  }
  explicit VariantHelper(VARTYPE type) {
    vt = type;
  }
  ~VariantHelper() {
    ::VariantClear(this);
  }
 private:
  DISALLOW_COPY_AND_ASSIGN(VariantHelper);
};

}  // namespace

bool WMI::CreateLocalConnection(bool set_blanket,
                                IWbemServices** wmi_services) {
  base::win::ScopedComPtr<IWbemLocator> wmi_locator;
  HRESULT hr = wmi_locator.CreateInstance(CLSID_WbemLocator, NULL,
                                          CLSCTX_INPROC_SERVER);
  if (FAILED(hr))
    return false;

  base::win::ScopedComPtr<IWbemServices> wmi_services_r;
  hr = wmi_locator->ConnectServer(base::win::ScopedBstr(L"ROOT\\CIMV2"),
                                  NULL, NULL, 0, NULL, 0, 0,
                                  wmi_services_r.Receive());
  if (FAILED(hr))
    return false;

  if (set_blanket) {
    hr = ::CoSetProxyBlanket(wmi_services_r,
                             RPC_C_AUTHN_WINNT,
                             RPC_C_AUTHZ_NONE,
                             NULL,
                             RPC_C_AUTHN_LEVEL_CALL,
                             RPC_C_IMP_LEVEL_IMPERSONATE,
                             NULL,
                             EOAC_NONE);
    if (FAILED(hr))
      return false;
  }

  *wmi_services = wmi_services_r.Detach();
  return true;
}

bool WMI::CreateClassMethodObject(IWbemServices* wmi_services,
                                  const std::wstring& class_name,
                                  const std::wstring& method_name,
                                  IWbemClassObject** class_instance) {
  // We attempt to instantiate a COM object that represents a WMI object plus
  // a method rolled into one entity.
  base::win::ScopedBstr b_class_name(class_name.c_str());
  base::win::ScopedBstr b_method_name(method_name.c_str());
  base::win::ScopedComPtr<IWbemClassObject> class_object;
  HRESULT hr;
  hr = wmi_services->GetObject(b_class_name, 0, NULL,
                               class_object.Receive(), NULL);
  if (FAILED(hr))
    return false;

  base::win::ScopedComPtr<IWbemClassObject> params_def;
  hr = class_object->GetMethod(b_method_name, 0, params_def.Receive(), NULL);
  if (FAILED(hr))
    return false;

  if (NULL == params_def) {
    // You hit this special case if the WMI class is not a CIM class. MSDN
    // sometimes tells you this. Welcome to WMI hell.
    return false;
  }

  hr = params_def->SpawnInstance(0, class_instance);
  return(SUCCEEDED(hr));
}

bool SetParameter(IWbemClassObject* class_method,
                  const std::wstring& parameter_name, VARIANT* parameter) {
  HRESULT hr = class_method->Put(parameter_name.c_str(), 0, parameter, 0);
  return SUCCEEDED(hr);
}

// The code in Launch() basically calls the Create Method of the Win32_Process
// CIM class is documented here:
// http://msdn2.microsoft.com/en-us/library/aa389388(VS.85).aspx

bool WMIProcess::Launch(const std::wstring& command_line, int* process_id) {
  base::win::ScopedComPtr<IWbemServices> wmi_local;
  if (!WMI::CreateLocalConnection(true, wmi_local.Receive()))
    return false;

  const wchar_t class_name[] = L"Win32_Process";
  const wchar_t method_name[] = L"Create";
  base::win::ScopedComPtr<IWbemClassObject> process_create;
  if (!WMI::CreateClassMethodObject(wmi_local, class_name, method_name,
                                    process_create.Receive()))
    return false;

  VariantHelper b_command_line(VT_BSTR);
  b_command_line.bstrVal = ::SysAllocString(command_line.c_str());

  if (!SetParameter(process_create, L"CommandLine", &b_command_line))
    return false;

  base::win::ScopedComPtr<IWbemClassObject> out_params;
  HRESULT hr = wmi_local->ExecMethod(base::win::ScopedBstr(class_name),
                                     base::win::ScopedBstr(method_name),
                                     0, NULL, process_create,
                                     out_params.Receive(), NULL);
  if (FAILED(hr))
    return false;

  VariantHelper ret_value;
  hr = out_params->Get(L"ReturnValue", 0, &ret_value, NULL, 0);
  if (FAILED(hr) || (0 != ret_value.uintVal))
    return false;

  VariantHelper pid;
  hr = out_params->Get(L"ProcessId", 0, &pid, NULL, 0);
  if (FAILED(hr) || (0 == pid.intVal))
    return false;

  if (process_id)
    *process_id = pid.intVal;

  return true;
}

string16 WMIComputerSystem::GetModel() {
  base::win::ScopedComPtr<IWbemServices> services;
  if (!WMI::CreateLocalConnection(true, services.Receive()))
    return string16();

  base::win::ScopedBstr query_language(L"WQL");
  base::win::ScopedBstr query(L"SELECT * FROM Win32_ComputerSystem");
  base::win::ScopedComPtr<IEnumWbemClassObject> enumerator;
  HRESULT hr = services->ExecQuery(
      query_language, query,
      WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL,
      enumerator.Receive());
  if (FAILED(hr) || !enumerator)
    return string16();

  base::win::ScopedComPtr<IWbemClassObject> class_object;
  ULONG items_returned = 0;
  hr = enumerator->Next(WBEM_INFINITE, 1,  class_object.Receive(),
                        &items_returned);
  if (!items_returned)
    return string16();

  base::win::ScopedVariant manufacturer;
  class_object->Get(L"Manufacturer", 0, manufacturer.Receive(), 0, 0);
  base::win::ScopedVariant model;
  class_object->Get(L"Model", 0, model.Receive(), 0, 0);

  string16 model_string;
  if (manufacturer.type() == VT_BSTR) {
    model_string = V_BSTR(&manufacturer);
    if (model.type() == VT_BSTR)
      model_string += L" ";
  }
  if (model.type() == VT_BSTR)
    model_string += V_BSTR(&model);

  return model_string;
}

}  // namespace installer
<commit_msg>Take care of an old todo: Use ScopedVariant instead of VariantHelper.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/installer/util/wmi.h"

#include <windows.h>

#include "base/basictypes.h"
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_variant.h"

#pragma comment(lib, "wbemuuid.lib")

using base::win::ScopedVariant;

namespace installer {

bool WMI::CreateLocalConnection(bool set_blanket,
                                IWbemServices** wmi_services) {
  base::win::ScopedComPtr<IWbemLocator> wmi_locator;
  HRESULT hr = wmi_locator.CreateInstance(CLSID_WbemLocator, NULL,
                                          CLSCTX_INPROC_SERVER);
  if (FAILED(hr))
    return false;

  base::win::ScopedComPtr<IWbemServices> wmi_services_r;
  hr = wmi_locator->ConnectServer(base::win::ScopedBstr(L"ROOT\\CIMV2"),
                                  NULL, NULL, 0, NULL, 0, 0,
                                  wmi_services_r.Receive());
  if (FAILED(hr))
    return false;

  if (set_blanket) {
    hr = ::CoSetProxyBlanket(wmi_services_r,
                             RPC_C_AUTHN_WINNT,
                             RPC_C_AUTHZ_NONE,
                             NULL,
                             RPC_C_AUTHN_LEVEL_CALL,
                             RPC_C_IMP_LEVEL_IMPERSONATE,
                             NULL,
                             EOAC_NONE);
    if (FAILED(hr))
      return false;
  }

  *wmi_services = wmi_services_r.Detach();
  return true;
}

bool WMI::CreateClassMethodObject(IWbemServices* wmi_services,
                                  const std::wstring& class_name,
                                  const std::wstring& method_name,
                                  IWbemClassObject** class_instance) {
  // We attempt to instantiate a COM object that represents a WMI object plus
  // a method rolled into one entity.
  base::win::ScopedBstr b_class_name(class_name.c_str());
  base::win::ScopedBstr b_method_name(method_name.c_str());
  base::win::ScopedComPtr<IWbemClassObject> class_object;
  HRESULT hr;
  hr = wmi_services->GetObject(b_class_name, 0, NULL,
                               class_object.Receive(), NULL);
  if (FAILED(hr))
    return false;

  base::win::ScopedComPtr<IWbemClassObject> params_def;
  hr = class_object->GetMethod(b_method_name, 0, params_def.Receive(), NULL);
  if (FAILED(hr))
    return false;

  if (NULL == params_def) {
    // You hit this special case if the WMI class is not a CIM class. MSDN
    // sometimes tells you this. Welcome to WMI hell.
    return false;
  }

  hr = params_def->SpawnInstance(0, class_instance);
  return(SUCCEEDED(hr));
}

bool SetParameter(IWbemClassObject* class_method,
                  const std::wstring& parameter_name, VARIANT* parameter) {
  HRESULT hr = class_method->Put(parameter_name.c_str(), 0, parameter, 0);
  return SUCCEEDED(hr);
}

// The code in Launch() basically calls the Create Method of the Win32_Process
// CIM class is documented here:
// http://msdn2.microsoft.com/en-us/library/aa389388(VS.85).aspx
// NOTE: The documentation for the Create method suggests that the ProcessId
// parameter and return value are of type uint32, but when we call the method
// the values in the returned out_params, are VT_I4, which is int32.

bool WMIProcess::Launch(const std::wstring& command_line, int* process_id) {
  base::win::ScopedComPtr<IWbemServices> wmi_local;
  if (!WMI::CreateLocalConnection(true, wmi_local.Receive()))
    return false;

  const wchar_t class_name[] = L"Win32_Process";
  const wchar_t method_name[] = L"Create";
  base::win::ScopedComPtr<IWbemClassObject> process_create;
  if (!WMI::CreateClassMethodObject(wmi_local, class_name, method_name,
                                    process_create.Receive()))
    return false;

  ScopedVariant b_command_line(command_line.c_str());

  if (!SetParameter(process_create, L"CommandLine", b_command_line.AsInput()))
    return false;

  base::win::ScopedComPtr<IWbemClassObject> out_params;
  HRESULT hr = wmi_local->ExecMethod(base::win::ScopedBstr(class_name),
                                     base::win::ScopedBstr(method_name),
                                     0, NULL, process_create,
                                     out_params.Receive(), NULL);
  if (FAILED(hr))
    return false;

  // We're only expecting int32 or uint32 values, so no need for ScopedVariant.
  VARIANT ret_value = {VT_EMPTY};
  hr = out_params->Get(L"ReturnValue", 0, &ret_value, NULL, 0);
  if (FAILED(hr) || 0 != V_I4(&ret_value))
    return false;

  VARIANT pid = {VT_EMPTY};
  hr = out_params->Get(L"ProcessId", 0, &pid, NULL, 0);
  if (FAILED(hr) || 0 == V_I4(&pid))
    return false;

  if (process_id)
    *process_id = V_I4(&pid);

  return true;
}

string16 WMIComputerSystem::GetModel() {
  base::win::ScopedComPtr<IWbemServices> services;
  if (!WMI::CreateLocalConnection(true, services.Receive()))
    return string16();

  base::win::ScopedBstr query_language(L"WQL");
  base::win::ScopedBstr query(L"SELECT * FROM Win32_ComputerSystem");
  base::win::ScopedComPtr<IEnumWbemClassObject> enumerator;
  HRESULT hr = services->ExecQuery(
      query_language, query,
      WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL,
      enumerator.Receive());
  if (FAILED(hr) || !enumerator)
    return string16();

  base::win::ScopedComPtr<IWbemClassObject> class_object;
  ULONG items_returned = 0;
  hr = enumerator->Next(WBEM_INFINITE, 1,  class_object.Receive(),
                        &items_returned);
  if (!items_returned)
    return string16();

  base::win::ScopedVariant manufacturer;
  class_object->Get(L"Manufacturer", 0, manufacturer.Receive(), 0, 0);
  base::win::ScopedVariant model;
  class_object->Get(L"Model", 0, model.Receive(), 0, 0);

  string16 model_string;
  if (manufacturer.type() == VT_BSTR) {
    model_string = V_BSTR(&manufacturer);
    if (model.type() == VT_BSTR)
      model_string += L" ";
  }
  if (model.type() == VT_BSTR)
    model_string += V_BSTR(&model);

  return model_string;
}

}  // namespace installer
<|endoftext|>


<commit_before>//===-- shm.cpp -----------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Save/restore via shared memory to survive exec*()
//
//===----------------------------------------------------------------------===//

#include "shm.h"

#include "ipcreg_internal.h"
#include "magic_socket_nums.h"
#include "real.h"
#include "rename_fd.h"

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#define UC(ret, msg) \
  unixCheck(ret, msg, __FILE__, __LINE__, __PRETTY_FUNCTION__);

void unixCheck(int ret, const char *msg, const char *file, unsigned line,
               const char *func, int err = errno) {
  if (ret == -1) {
    ipclog("Unix call failed in %s at %s:%u: %s - %s\n", func, file, line, msg,
           strerror(err));
    abort();
  }
}

static char buf[100];
const char *getShmName() {
  sprintf(buf, "/ipcd.%d\n", getpid());
  return buf;
}

int get_shm(int flags, mode_t mode) {
  int fd = shm_open(getShmName(), flags, mode);
  if (fd == EEXIST) {
    ipclog("Shared memory segment exists, attempting to remove it...\n");
    int ret = shm_unlink(getShmName());
    UC(ret, "Closing existing shm");

    // Okay, let's try this again
    fd = shm_open(getShmName(), flags, mode);
  }
  UC(fd, "shm_open");
  UC(fchmod(fd, mode), "fchmod on shared memory segment");
  return fd;
}

void shm_state_save() {
  // Create shared memory segment
  int fd = get_shm(O_RDWR | O_CREAT | O_EXCL, 0600);
  UC(fd, "get_shm");

  bool success = rename_fd(fd, MAGIC_SHM_FD, /* cloexec */ false);
  assert(success && "Failed to rename SHM fd!");

  // Do *not* close on exec! :)
  int flags = __real_fcntl(MAGIC_SHM_FD, F_GETFD, /* kludge */ 0);
  assert(flags >= 0);
  flags &= ~FD_CLOEXEC;
  int ret = __real_fcntl_int(MAGIC_SHM_FD, F_SETFD, flags);
  UC(ret, "fcntl CLOEXEC on shared memory segment");

  // Size the memory segment:
  ret = ftruncate(MAGIC_SHM_FD, sizeof(libipc_state));
  UC(ret, "ftruncate on shm");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                  MAP_SHARED, MAGIC_SHM_FD, 0);
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  *(libipc_state*)stateptr = state;

  // Unmap, but don't unlink the shared memory
  ret = munmap(stateptr, sizeof(libipc_state));
  UC(ret, "unmap shm");

  ipclog("State saved!\n");
}

bool is_valid_fd(int fd) {
  return __real_fcntl(fd, F_GETFD, /* kludge */ 0) >= 0;
}

void shm_state_restore() {
  // If we have memory to restore, it'll be in our magic FD!
  if (!is_valid_fd(MAGIC_SHM_FD))
    return;

  ipclog("Inherited ipc state FD, starting state restoration...\n");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                        MAP_SHARED, MAGIC_SHM_FD, 0);
  // If our FD is still open, the memory better still be there!
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  // Copy state from shared memory segment
  state = *(libipc_state*)stateptr;

  int ret = munmap(stateptr, sizeof(libipc_state));
  UC(ret, "unmap shm");

  // Done with the shared segment, thank you!
  ret = __real_close(MAGIC_SHM_FD);
  UC(ret, "close shm");
  ret = shm_unlink(getShmName());
  UC(ret, "shm_unlink after close");

  ipclog("State restored!\n");
}

void shm_state_destroy() {
  // If we have memory to restore, it'll be in our magic FD!
  assert(is_valid_fd(MAGIC_SHM_FD));

  int ret = __real_close(MAGIC_SHM_FD);
  assert(ret == 0);

  ret = shm_unlink(getShmName());
  UC(ret, "shm_unlink");

  ipclog("Destroyed saved state!\n");
}
<commit_msg>shm: Heh, actually detect EEXIST on shm_open attempt.<commit_after>//===-- shm.cpp -----------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Save/restore via shared memory to survive exec*()
//
//===----------------------------------------------------------------------===//

#include "shm.h"

#include "ipcreg_internal.h"
#include "magic_socket_nums.h"
#include "real.h"
#include "rename_fd.h"

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#define UC(ret, msg) \
  unixCheck(ret, msg, __FILE__, __LINE__, __PRETTY_FUNCTION__);

void unixCheck(int ret, const char *msg, const char *file, unsigned line,
               const char *func, int err = errno) {
  if (ret == -1) {
    ipclog("Unix call failed in %s at %s:%u: %s - %s\n", func, file, line, msg,
           strerror(err));
    abort();
  }
}

static char buf[100];
const char *getShmName() {
  sprintf(buf, "/ipcd.%d\n", getpid());
  return buf;
}

int get_shm(int flags, mode_t mode) {
  int fd = shm_open(getShmName(), flags, mode);
  if (fd == -1 && errno == EEXIST) {
    ipclog("Shared memory segment exists, attempting to remove it...\n");
    int ret = shm_unlink(getShmName());
    UC(ret, "Closing existing shm");

    // Okay, let's try this again
    fd = shm_open(getShmName(), flags, mode);
  }
  UC(fd, "shm_open");
  UC(fchmod(fd, mode), "fchmod on shared memory segment");
  return fd;
}

void shm_state_save() {
  // Create shared memory segment
  int fd = get_shm(O_RDWR | O_CREAT | O_EXCL, 0600);
  UC(fd, "get_shm");

  bool success = rename_fd(fd, MAGIC_SHM_FD, /* cloexec */ false);
  assert(success && "Failed to rename SHM fd!");

  // Do *not* close on exec! :)
  int flags = __real_fcntl(MAGIC_SHM_FD, F_GETFD, /* kludge */ 0);
  assert(flags >= 0);
  flags &= ~FD_CLOEXEC;
  int ret = __real_fcntl_int(MAGIC_SHM_FD, F_SETFD, flags);
  UC(ret, "fcntl CLOEXEC on shared memory segment");

  // Size the memory segment:
  ret = ftruncate(MAGIC_SHM_FD, sizeof(libipc_state));
  UC(ret, "ftruncate on shm");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                  MAP_SHARED, MAGIC_SHM_FD, 0);
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  *(libipc_state*)stateptr = state;

  // Unmap, but don't unlink the shared memory
  ret = munmap(stateptr, sizeof(libipc_state));
  UC(ret, "unmap shm");

  ipclog("State saved!\n");
}

bool is_valid_fd(int fd) {
  return __real_fcntl(fd, F_GETFD, /* kludge */ 0) >= 0;
}

void shm_state_restore() {
  // If we have memory to restore, it'll be in our magic FD!
  if (!is_valid_fd(MAGIC_SHM_FD))
    return;

  ipclog("Inherited ipc state FD, starting state restoration...\n");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                        MAP_SHARED, MAGIC_SHM_FD, 0);
  // If our FD is still open, the memory better still be there!
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  // Copy state from shared memory segment
  state = *(libipc_state*)stateptr;

  int ret = munmap(stateptr, sizeof(libipc_state));
  UC(ret, "unmap shm");

  // Done with the shared segment, thank you!
  ret = __real_close(MAGIC_SHM_FD);
  UC(ret, "close shm");
  ret = shm_unlink(getShmName());
  UC(ret, "shm_unlink after close");

  ipclog("State restored!\n");
}

void shm_state_destroy() {
  // If we have memory to restore, it'll be in our magic FD!
  assert(is_valid_fd(MAGIC_SHM_FD));

  int ret = __real_close(MAGIC_SHM_FD);
  assert(ret == 0);

  ret = shm_unlink(getShmName());
  UC(ret, "shm_unlink");

  ipclog("Destroyed saved state!\n");
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/nacl/nacl_listener.h"

#include <errno.h>

#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "chrome/common/nacl_messages.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_switches.h"
#include "native_client/src/shared/imc/nacl_imc.h"
#include "native_client/src/trusted/service_runtime/sel_main_chrome.h"

#if defined(OS_LINUX)
#include "content/public/common/child_process_sandbox_support_linux.h"
#endif

#if defined(OS_WIN)
#include <fcntl.h>
#include <io.h>
#endif

#if defined(OS_MACOSX)
namespace {

// On Mac OS X, shm_open() works in the sandbox but does not give us
// an FD that we can map as PROT_EXEC.  Rather than doing an IPC to
// get an executable SHM region when CreateMemoryObject() is called,
// we preallocate one on startup, since NaCl's sel_ldr only needs one
// of them.  This saves a round trip.

base::subtle::Atomic32 g_shm_fd = -1;

int CreateMemoryObject(size_t size, bool executable) {
  if (executable && size > 0) {
    int result_fd = base::subtle::NoBarrier_AtomicExchange(&g_shm_fd, -1);
    if (result_fd != -1) {
      // ftruncate() is disallowed by the Mac OS X sandbox and
      // returns EPERM.  Luckily, we can get the same effect with
      // lseek() + write().
      if (lseek(result_fd, size - 1, SEEK_SET) == -1) {
        LOG(ERROR) << "lseek() failed: " << errno;
        return -1;
      }
      if (write(result_fd, "", 1) != 1) {
        LOG(ERROR) << "write() failed: " << errno;
        return -1;
      }
      return result_fd;
    }
  }
  // Fall back to NaCl's default implementation.
  return -1;
}

}  // namespace
#endif  // defined(OS_MACOSX)

NaClListener::NaClListener() : debug_enabled_(false) {}

NaClListener::~NaClListener() {}

void NaClListener::Listen() {
  std::string channel_name =
      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          switches::kProcessChannelID);
  IPC::Channel channel(channel_name, IPC::Channel::MODE_CLIENT, this);
  CHECK(channel.Connect());
  MessageLoop::current()->Run();
}

bool NaClListener::OnMessageReceived(const IPC::Message& msg) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(NaClListener, msg)
      IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStartSelLdr)
      IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void NaClListener::OnStartSelLdr(std::vector<nacl::FileDescriptor> handles) {
#if defined(OS_LINUX)
  nacl::SetCreateMemoryObjectFunc(content::MakeSharedMemorySegmentViaIPC);
#elif defined(OS_MACOSX)
  nacl::SetCreateMemoryObjectFunc(CreateMemoryObject);
  CHECK(handles.size() >= 1);
  g_shm_fd = nacl::ToNativeHandle(handles[handles.size() - 1]);
  handles.pop_back();
#endif

  CHECK(handles.size() >= 1);
  NaClHandle irt_handle = nacl::ToNativeHandle(handles[handles.size() - 1]);
  handles.pop_back();

#if defined(OS_WIN)
  int irt_desc = _open_osfhandle(reinterpret_cast<intptr_t>(irt_handle),
                                 _O_RDONLY | _O_BINARY);
  if (irt_desc < 0) {
    LOG(ERROR) << "_open_osfhandle() failed";
    return;
  }
#else
  int irt_desc = irt_handle;
#endif

  NaClSetIrtFileDesc(irt_desc);

  scoped_array<NaClHandle> array(new NaClHandle[handles.size()]);
  for (size_t i = 0; i < handles.size(); i++) {
    array[i] = nacl::ToNativeHandle(handles[i]);
  }
  NaClMainForChromium(static_cast<int>(handles.size()), array.get(),
                      debug_enabled_);
  NOTREACHED();
}
<commit_msg>NaCl: Switch to using the new extensible startup interface<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/nacl/nacl_listener.h"

#include <errno.h>

#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "chrome/common/nacl_messages.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_switches.h"
#include "native_client/src/trusted/service_runtime/sel_main_chrome.h"

#if defined(OS_LINUX)
#include "content/public/common/child_process_sandbox_support_linux.h"
#endif

#if defined(OS_WIN)
#include <fcntl.h>
#include <io.h>
#endif

namespace {
#if defined(OS_MACOSX)

// On Mac OS X, shm_open() works in the sandbox but does not give us
// an FD that we can map as PROT_EXEC.  Rather than doing an IPC to
// get an executable SHM region when CreateMemoryObject() is called,
// we preallocate one on startup, since NaCl's sel_ldr only needs one
// of them.  This saves a round trip.

base::subtle::Atomic32 g_shm_fd = -1;

int CreateMemoryObject(size_t size, int executable) {
  if (executable && size > 0) {
    int result_fd = base::subtle::NoBarrier_AtomicExchange(&g_shm_fd, -1);
    if (result_fd != -1) {
      // ftruncate() is disallowed by the Mac OS X sandbox and
      // returns EPERM.  Luckily, we can get the same effect with
      // lseek() + write().
      if (lseek(result_fd, size - 1, SEEK_SET) == -1) {
        LOG(ERROR) << "lseek() failed: " << errno;
        return -1;
      }
      if (write(result_fd, "", 1) != 1) {
        LOG(ERROR) << "write() failed: " << errno;
        return -1;
      }
      return result_fd;
    }
  }
  // Fall back to NaCl's default implementation.
  return -1;
}

#elif defined(OS_LINUX)

int CreateMemoryObject(size_t size, int executable) {
  return content::MakeSharedMemorySegmentViaIPC(size, executable);
}

#endif
}  // namespace

NaClListener::NaClListener() : debug_enabled_(false) {}

NaClListener::~NaClListener() {}

void NaClListener::Listen() {
  std::string channel_name =
      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          switches::kProcessChannelID);
  IPC::Channel channel(channel_name, IPC::Channel::MODE_CLIENT, this);
  CHECK(channel.Connect());
  MessageLoop::current()->Run();
}

bool NaClListener::OnMessageReceived(const IPC::Message& msg) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(NaClListener, msg)
      IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStartSelLdr)
      IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void NaClListener::OnStartSelLdr(std::vector<nacl::FileDescriptor> handles) {
  struct NaClChromeMainArgs *args = NaClChromeMainArgsCreate();
  if (args == NULL) {
    LOG(ERROR) << "NaClChromeMainArgsCreate() failed";
    return;
  }

#if defined(OS_LINUX) || defined(OS_MACOSX)
  args->create_memory_object_func = CreateMemoryObject;
# if defined(OS_MACOSX)
  CHECK(handles.size() >= 1);
  g_shm_fd = nacl::ToNativeHandle(handles[handles.size() - 1]);
  handles.pop_back();
# endif
#endif

  CHECK(handles.size() >= 1);
  NaClHandle irt_handle = nacl::ToNativeHandle(handles[handles.size() - 1]);
  handles.pop_back();

#if defined(OS_WIN)
  args->irt_fd = _open_osfhandle(reinterpret_cast<intptr_t>(irt_handle),
                                 _O_RDONLY | _O_BINARY);
  if (args->irt_fd < 0) {
    LOG(ERROR) << "_open_osfhandle() failed";
    return;
  }
#else
  args->irt_fd = irt_handle;
#endif

  CHECK(handles.size() == 1);
  args->imc_bootstrap_handle = nacl::ToNativeHandle(handles[0]);
  args->enable_debug_stub = debug_enabled_;
  NaClChromeMainStart(args);
  NOTREACHED();
}
<|endoftext|>


<commit_before>#include "etl/armv7m/exception_table.h"
#include "etl/common/attribute_macros.h"

ETL_NORETURN void etl_armv7m_reset_handler() {
  while (1);
}

// Generate traps for all unused exception vectors.
#define ETL_ARMV7M_EXCEPTION(name) \
  ETL_NORETURN void etl_armv7m_ ## name ## _handler() { \
    while (1); \
  }

#define ETL_ARMV7M_EXCEPTION_RESERVED(n)

#include "etl/armv7m/exceptions.def"
<commit_msg>wip minimal<commit_after>#include "etl/armv7m/exception_table.h"
#include "etl/common/attribute_macros.h"

#include "etl/armv7m/nvic.h"
#include "etl/armv7m/scb.h"

ETL_NORETURN void etl_armv7m_reset_handler() {
  etl::armv7m::scb.enable_faults();
  while (1);
}

// Generate traps for all unused exception vectors.
#define ETL_ARMV7M_EXCEPTION(name) \
  ETL_NORETURN void etl_armv7m_ ## name ## _handler() { \
    while (1); \
  }

#define ETL_ARMV7M_EXCEPTION_RESERVED(n)

#include "etl/armv7m/exceptions.def"
<|endoftext|>


<commit_before>/*-----------------------------------------------------------------------------------------------
The MIT License (MIT)

Copyright (c) 2014-2015 Kim Kulling

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------------------------------*/
#include <openddlparser/Value.h>

#include <iostream>
#include <cassert>

BEGIN_ODDLPARSER_NS

static Value::Iterator end( ddl_nullptr );

Value::Iterator::Iterator()
: m_start( ddl_nullptr )
, m_current( ddl_nullptr ) {
    // empty
}

Value::Iterator::Iterator( Value *start )
: m_start( start )
, m_current( start ) {
    // empty
}

Value::Iterator::Iterator( const Iterator &rhs )
: m_start( rhs.m_start )
, m_current( rhs.m_current ) {
    // empty
}

Value::Iterator::~Iterator() {
    // empty
}

bool Value::Iterator::hasNext() const {
    if( ddl_nullptr == m_current ) {
        return false;
    }
    return ( ddl_nullptr != m_current->getNext() );
}

Value *Value::Iterator::getNext() {
    if( !hasNext() ) {
        return ddl_nullptr;
    }

    Value *v( m_current->getNext() );
    m_current = v;

    return v;
}

const Value::Iterator Value::Iterator::operator++( int ) {
    if( ddl_nullptr == m_current ) {
        return end;
    }

    m_current = m_current->getNext();
    Iterator inst( m_current );

    return inst;
}

Value::Iterator &Value::Iterator::operator++( ) {
    if( ddl_nullptr == m_current ) {
        return end;
    }

    m_current = m_current->getNext();

    return *this;
}

bool Value::Iterator::operator == ( const Iterator &rhs ) const {
    return ( m_current == rhs.m_current );
}

Value *Value::Iterator::operator->( ) const {
    if( nullptr == m_current ) {
        return ddl_nullptr;
    }
    return m_current;
}

Value::Value( ValueType type )
: m_type( type )
, m_size( 0 )
, m_data( ddl_nullptr )
, m_next( ddl_nullptr ) {
    // empty
}

Value::~Value() {
    // empty
}

void Value::setBool( bool value ) {
    assert( ddl_bool == m_type );
    ::memcpy( m_data, &value, m_size );
}

bool Value::getBool() {
    assert( ddl_bool == m_type );

    return ( *m_data == 1 );
}

void Value::setInt8( int8 value ) {
    assert( ddl_int8 == m_type );
    ::memcpy( m_data, &value, m_size );
}

int8 Value::getInt8() {
    assert( ddl_int8 == m_type );
    return ( int8 ) ( *m_data );
}

void Value::setInt16( int16 value ) {
    assert( ddl_int16 == m_type );
    ::memcpy( m_data, &value, m_size );
}

int16 Value::getInt16() {
    assert( ddl_int16 == m_type );
    int16 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setInt32( int32 value ) {
    assert( ddl_int32 == m_type );
    ::memcpy( m_data, &value, m_size );
}

int32 Value::getInt32() {
    assert( ddl_int32 == m_type );
    int32 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setInt64( int64 value ) {
    assert( ddl_int64 == m_type );
    ::memcpy( m_data, &value, m_size );
}

int64 Value::getInt64() {
    assert( ddl_int64 == m_type );
    int64 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setUnsignedInt8( uint8 value ) {
    assert( ddl_unsigned_int8 == m_type );
    ::memcpy( m_data, &value, m_size );
}

uint8 Value::getUnsignedInt8() const {
    assert( ddl_unsigned_int8 == m_type );
    uint8 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setUnsignedInt16( uint16 value ) {
    assert( ddl_unsigned_int16 == m_type );
    ::memcpy( m_data, &value, m_size );
}

uint16 Value::getUnsignedInt16() const {
    assert( ddl_unsigned_int16 == m_type );
    uint16 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setUnsignedInt32( uint32 value ) {
    assert( ddl_unsigned_int32 == m_type );
    ::memcpy( m_data, &value, m_size );
}

uint32 Value::getUnsignedInt32() const {
    assert( ddl_unsigned_int32 == m_type );
    uint32 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setUnsignedInt64( uint64 value ) {
    assert( ddl_unsigned_int64 == m_type );
    ::memcpy( m_data, &value, m_size );
}

uint64 Value::getUnsignedInt64() const {
    assert( ddl_unsigned_int64 == m_type );
    uint64 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setFloat( float value ) {
    assert( ddl_float == m_type );
    ::memcpy( m_data, &value, m_size );
}

float Value::getFloat() const {
    if( m_type == ddl_float ) {
        float v;
        ::memcpy( &v, m_data, m_size );
        return ( float ) v;
    } else {
        float tmp;
        ::memcpy( &tmp, m_data, 4 );
        return ( float ) tmp;
    }
}

void Value::setDouble( double value ) {
    assert( ddl_double == m_type );
    ::memcpy( m_data, &value, m_size );
}

double Value::getDouble() const {
    double v;
    ::memcpy( &v, m_data, m_size );
    return v;
}

void Value::setString( const std::string &str ) {
    assert( ddl_string == m_type );
    ::memcpy( m_data, str.c_str(), str.size() );
    m_data[ str.size() ] = '\0';
}
const char *Value::getString() const {
    return (const char*) m_data;
}

void Value::dump() {
    switch( m_type ) {
    case ddl_none:
        std::cout << "None" << std::endl;
        break;
    case ddl_bool:
        std::cout << getBool() << std::endl;
        break;
    case ddl_int8:
        std::cout << getInt8() << std::endl;
        break;
    case ddl_int16:
        std::cout << getInt16() << std::endl;
        break;
    case ddl_int32:
        std::cout << getInt32() << std::endl;
        break;
    case ddl_int64:
        std::cout << getInt64() << std::endl;
        break;
    case ddl_unsigned_int8:
        std::cout << "Not supported" << std::endl;
        break;
    case ddl_unsigned_int16:
        std::cout << "Not supported" << std::endl;
        break;
    case ddl_unsigned_int32:
        std::cout << "Not supported" << std::endl;
        break;
    case ddl_unsigned_int64:
        std::cout << "Not supported" << std::endl;
        break;
    case ddl_half:
        std::cout << "Not supported" << std::endl;
        break;
    case ddl_float:
        std::cout << getFloat() << std::endl;
        break;
    case ddl_double:
        std::cout << getDouble() << std::endl;
        break;
    case ddl_string:
        std::cout << "Not supported" << std::endl;
        break;
    case ddl_ref:
        std::cout << "Not supported" << std::endl;
        break;
    default:
        break;
    }
}

void Value::setNext( Value *next ) {
    m_next = next;
}

Value *Value::getNext() const {
    return m_next;
}

Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
    if( type == Value::ddl_none || Value::ddl_types_max == type ) {
        return ddl_nullptr;
    }

    Value *data = new Value( type );
    data->m_type = type;
    switch( type ) {
        case Value::ddl_bool:
            data->m_size = sizeof( bool );
            break;
        case Value::ddl_int8:
            data->m_size = sizeof( int8 );
            break;
        case Value::ddl_int16:
            data->m_size = sizeof( int16 );
            break;
        case Value::ddl_int32:
            data->m_size = sizeof( int32 );
            break;
        case Value::ddl_int64:
            data->m_size = sizeof( int64 );
            break;
        case Value::ddl_unsigned_int8:
            data->m_size = sizeof( uint8 );
            break;
        case Value::ddl_unsigned_int16:
            data->m_size = sizeof( uint16 );
            break;
        case Value::ddl_unsigned_int32:
            data->m_size = sizeof( uint32 );
            break;
        case Value::ddl_unsigned_int64:
            data->m_size = sizeof( uint64 );
            break;
        case Value::ddl_half:
            data->m_size = sizeof( short );
            break;
        case Value::ddl_float:
            data->m_size = sizeof( float );
            break;
        case Value::ddl_double:
            data->m_size = sizeof( double );
            break;
        case Value::ddl_string:
            data->m_size = sizeof( char );
            break;
        case Value::ddl_ref:
            data->m_size = sizeof( char );
            break;
        case Value::ddl_none:
        case Value::ddl_types_max:
        default:
            break;
    }

    if( data->m_size ) {
        size_t len1( len );
        if( Value::ddl_string == type ) {
            len1++;
        }
        data->m_size *= len1;
        data->m_data = new unsigned char[ data->m_size ];
    }

    return data;
}

void ValueAllocator::releasePrimData( Value **data ) {
    if( !data ) {
        return;
    }

    delete *data;
    *data = ddl_nullptr;
}

END_ODDLPARSER_NS
<commit_msg>Value: add missing assert test.<commit_after>/*-----------------------------------------------------------------------------------------------
The MIT License (MIT)

Copyright (c) 2014-2015 Kim Kulling

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------------------------------*/
#include <openddlparser/Value.h>

#include <iostream>
#include <cassert>

BEGIN_ODDLPARSER_NS

static Value::Iterator end( ddl_nullptr );

Value::Iterator::Iterator()
: m_start( ddl_nullptr )
, m_current( ddl_nullptr ) {
    // empty
}

Value::Iterator::Iterator( Value *start )
: m_start( start )
, m_current( start ) {
    // empty
}

Value::Iterator::Iterator( const Iterator &rhs )
: m_start( rhs.m_start )
, m_current( rhs.m_current ) {
    // empty
}

Value::Iterator::~Iterator() {
    // empty
}

bool Value::Iterator::hasNext() const {
    if( ddl_nullptr == m_current ) {
        return false;
    }
    return ( ddl_nullptr != m_current->getNext() );
}

Value *Value::Iterator::getNext() {
    if( !hasNext() ) {
        return ddl_nullptr;
    }

    Value *v( m_current->getNext() );
    m_current = v;

    return v;
}

const Value::Iterator Value::Iterator::operator++( int ) {
    if( ddl_nullptr == m_current ) {
        return end;
    }

    m_current = m_current->getNext();
    Iterator inst( m_current );

    return inst;
}

Value::Iterator &Value::Iterator::operator++( ) {
    if( ddl_nullptr == m_current ) {
        return end;
    }

    m_current = m_current->getNext();

    return *this;
}

bool Value::Iterator::operator == ( const Iterator &rhs ) const {
    return ( m_current == rhs.m_current );
}

Value *Value::Iterator::operator->( ) const {
    if( nullptr == m_current ) {
        return ddl_nullptr;
    }
    return m_current;
}

Value::Value( ValueType type )
: m_type( type )
, m_size( 0 )
, m_data( ddl_nullptr )
, m_next( ddl_nullptr ) {
    // empty
}

Value::~Value() {
    // empty
}

void Value::setBool( bool value ) {
    assert( ddl_bool == m_type );
    ::memcpy( m_data, &value, m_size );
}

bool Value::getBool() {
    assert( ddl_bool == m_type );

    return ( *m_data == 1 );
}

void Value::setInt8( int8 value ) {
    assert( ddl_int8 == m_type );
    ::memcpy( m_data, &value, m_size );
}

int8 Value::getInt8() {
    assert( ddl_int8 == m_type );
    return ( int8 ) ( *m_data );
}

void Value::setInt16( int16 value ) {
    assert( ddl_int16 == m_type );
    ::memcpy( m_data, &value, m_size );
}

int16 Value::getInt16() {
    assert( ddl_int16 == m_type );
    int16 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setInt32( int32 value ) {
    assert( ddl_int32 == m_type );
    ::memcpy( m_data, &value, m_size );
}

int32 Value::getInt32() {
    assert( ddl_int32 == m_type );
    int32 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setInt64( int64 value ) {
    assert( ddl_int64 == m_type );
    ::memcpy( m_data, &value, m_size );
}

int64 Value::getInt64() {
    assert( ddl_int64 == m_type );
    int64 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setUnsignedInt8( uint8 value ) {
    assert( ddl_unsigned_int8 == m_type );
    ::memcpy( m_data, &value, m_size );
}

uint8 Value::getUnsignedInt8() const {
    assert( ddl_unsigned_int8 == m_type );
    uint8 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setUnsignedInt16( uint16 value ) {
    assert( ddl_unsigned_int16 == m_type );
    ::memcpy( m_data, &value, m_size );
}

uint16 Value::getUnsignedInt16() const {
    assert( ddl_unsigned_int16 == m_type );
    uint16 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setUnsignedInt32( uint32 value ) {
    assert( ddl_unsigned_int32 == m_type );
    ::memcpy( m_data, &value, m_size );
}

uint32 Value::getUnsignedInt32() const {
    assert( ddl_unsigned_int32 == m_type );
    uint32 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setUnsignedInt64( uint64 value ) {
    assert( ddl_unsigned_int64 == m_type );
    ::memcpy( m_data, &value, m_size );
}

uint64 Value::getUnsignedInt64() const {
    assert( ddl_unsigned_int64 == m_type );
    uint64 i;
    ::memcpy( &i, m_data, m_size );
    return i;
}

void Value::setFloat( float value ) {
    assert( ddl_float == m_type );
    ::memcpy( m_data, &value, m_size );
}

float Value::getFloat() const {
    if( m_type == ddl_float ) {
        float v;
        ::memcpy( &v, m_data, m_size );
        return ( float ) v;
    } else {
        float tmp;
        ::memcpy( &tmp, m_data, 4 );
        return ( float ) tmp;
    }
}

void Value::setDouble( double value ) {
    assert( ddl_double == m_type );
    ::memcpy( m_data, &value, m_size );
}

double Value::getDouble() const {
    assert( ddl_double == m_type );
    double v;
    ::memcpy( &v, m_data, m_size );
    return v;
}

void Value::setString( const std::string &str ) {
    assert( ddl_string == m_type );
    ::memcpy( m_data, str.c_str(), str.size() );
    m_data[ str.size() ] = '\0';
}
const char *Value::getString() const {
    assert( ddl_string == m_type );
    return (const char*) m_data;
}

void Value::dump() {
    switch( m_type ) {
    case ddl_none:
        std::cout << "None" << std::endl;
        break;
    case ddl_bool:
        std::cout << getBool() << std::endl;
        break;
    case ddl_int8:
        std::cout << getInt8() << std::endl;
        break;
    case ddl_int16:
        std::cout << getInt16() << std::endl;
        break;
    case ddl_int32:
        std::cout << getInt32() << std::endl;
        break;
    case ddl_int64:
        std::cout << getInt64() << std::endl;
        break;
    case ddl_unsigned_int8:
        std::cout << "Not supported" << std::endl;
        break;
    case ddl_unsigned_int16:
        std::cout << "Not supported" << std::endl;
        break;
    case ddl_unsigned_int32:
        std::cout << "Not supported" << std::endl;
        break;
    case ddl_unsigned_int64:
        std::cout << "Not supported" << std::endl;
        break;
    case ddl_half:
        std::cout << "Not supported" << std::endl;
        break;
    case ddl_float:
        std::cout << getFloat() << std::endl;
        break;
    case ddl_double:
        std::cout << getDouble() << std::endl;
        break;
    case ddl_string:
        std::cout << "Not supported" << std::endl;
        break;
    case ddl_ref:
        std::cout << "Not supported" << std::endl;
        break;
    default:
        break;
    }
}

void Value::setNext( Value *next ) {
    m_next = next;
}

Value *Value::getNext() const {
    return m_next;
}

Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) {
    if( type == Value::ddl_none || Value::ddl_types_max == type ) {
        return ddl_nullptr;
    }

    Value *data = new Value( type );
    data->m_type = type;
    switch( type ) {
        case Value::ddl_bool:
            data->m_size = sizeof( bool );
            break;
        case Value::ddl_int8:
            data->m_size = sizeof( int8 );
            break;
        case Value::ddl_int16:
            data->m_size = sizeof( int16 );
            break;
        case Value::ddl_int32:
            data->m_size = sizeof( int32 );
            break;
        case Value::ddl_int64:
            data->m_size = sizeof( int64 );
            break;
        case Value::ddl_unsigned_int8:
            data->m_size = sizeof( uint8 );
            break;
        case Value::ddl_unsigned_int16:
            data->m_size = sizeof( uint16 );
            break;
        case Value::ddl_unsigned_int32:
            data->m_size = sizeof( uint32 );
            break;
        case Value::ddl_unsigned_int64:
            data->m_size = sizeof( uint64 );
            break;
        case Value::ddl_half:
            data->m_size = sizeof( short );
            break;
        case Value::ddl_float:
            data->m_size = sizeof( float );
            break;
        case Value::ddl_double:
            data->m_size = sizeof( double );
            break;
        case Value::ddl_string:
            data->m_size = sizeof( char );
            break;
        case Value::ddl_ref:
            data->m_size = sizeof( char );
            break;
        case Value::ddl_none:
        case Value::ddl_types_max:
        default:
            break;
    }

    if( data->m_size ) {
        size_t len1( len );
        if( Value::ddl_string == type ) {
            len1++;
        }
        data->m_size *= len1;
        data->m_data = new unsigned char[ data->m_size ];
    }

    return data;
}

void ValueAllocator::releasePrimData( Value **data ) {
    if( !data ) {
        return;
    }

    delete *data;
    *data = ddl_nullptr;
}

END_ODDLPARSER_NS
<|endoftext|>