Rename files in runtime/base, part 6
[hiphop-php.git] / hphp / runtime / debugger / dummy_sandbox.cpp
blobb3b588945a5ccd94b681f5539cb66ab922cc800b
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/debugger/dummy_sandbox.h"
19 #include <boost/noncopyable.hpp>
21 #include "hphp/runtime/debugger/debugger.h"
22 #include "hphp/runtime/debugger/cmd/cmd_signal.h"
23 #include "hphp/runtime/base/program-functions.h"
24 #include "hphp/runtime/server/source_root_info.h"
25 #include "hphp/runtime/base/externals.h"
26 #include "hphp/runtime/base/hphp_system.h"
27 #include "hphp/util/logger.h"
28 #include "hphp/util/process.h"
30 namespace HPHP { namespace Eval {
31 ///////////////////////////////////////////////////////////////////////////////
32 TRACE_SET_MOD(debugger);
34 DummySandbox::DummySandbox(DebuggerProxy *proxy,
35 const std::string &defaultPath,
36 const std::string &startupFile)
37 : m_proxy(proxy), m_defaultPath(defaultPath), m_startupFile(startupFile),
38 m_thread(this, &DummySandbox::run), m_stopped(false),
39 m_signum(CmdSignal::SignalNone) { }
41 void DummySandbox::start() {
42 TRACE(2, "DummySandbox::start\n");
43 m_thread.start();
46 // Stop the sandbox thread, and wait for it to end. Timeout is in
47 // seconds. This can be called multiple times.
48 bool DummySandbox::stop(int timeout) {
49 TRACE(2, "DummySandbox::stop\n");
50 m_stopped = true;
51 notify(); // Wakeup the sandbox thread so it will notice the stopped flag
52 return m_thread.waitForEnd(timeout);
55 namespace {
57 struct CLISession : private boost::noncopyable {
58 CLISession() {
59 TRACE(2, "CLISession::CLISession\n");
60 char *argv[] = {"", nullptr};
61 execute_command_line_begin(1, argv, 0);
63 ~CLISession() {
64 TRACE(2, "CLISession::~CLISession\n");
65 Debugger::UnregisterSandbox(g_context->getSandboxId());
66 ThreadInfo::s_threadInfo.getNoCheck()->
67 m_reqInjectionData.setDebugger(false);
68 execute_command_line_end(0, false, nullptr);
74 const StaticString s__SERVER("_SERVER");
76 void DummySandbox::run() {
77 TRACE(2, "DummySandbox::run\n");
78 ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
79 Debugger::RegisterThread();
80 while (!m_stopped) {
81 try {
82 CLISession hphpSession;
84 DSandboxInfo sandbox = m_proxy->getSandbox();
85 string msg;
86 if (sandbox.valid()) {
87 GlobalVariables *g = get_global_variables();
88 SourceRootInfo sri(sandbox.m_user, sandbox.m_name);
89 if (sandbox.m_path.empty()) {
90 sandbox.m_path = sri.path();
92 if (!sri.sandboxOn()) {
93 msg = "Invalid sandbox was specified. "
94 "PHP files may not be loaded properly.\n";
95 } else {
96 sri.setServerVariables(g->getRef(s__SERVER));
98 Debugger::RegisterSandbox(sandbox);
99 g_context->setSandboxId(sandbox.id());
101 std::string doc = getStartupDoc(sandbox);
102 if (!doc.empty()) {
103 char cwd[PATH_MAX];
104 getcwd(cwd, sizeof(cwd));
105 Logger::Info("Start loading startup doc '%s', pwd = '%s'",
106 doc.c_str(), cwd);
107 bool error; string errorMsg;
108 bool ret = hphp_invoke(g_context.getNoCheck(), doc, false, null_array,
109 uninit_null(), "", "", error, errorMsg, true,
110 false, true);
111 if (!ret || error) {
112 msg += "Unable to pre-load " + doc;
113 if (!errorMsg.empty()) {
114 msg += ": " + errorMsg;
117 Logger::Info("Startup doc " + doc + " loaded");
119 } else {
120 g_context->setSandboxId(m_proxy->getDummyInfo().id());
123 ti->m_reqInjectionData.setDebugger(true);
125 DebuggerDummyEnv dde;
126 // This is really the entire point of having the dummy sandbox. This
127 // fires the initial session started interrupt to the client after
128 // it first attaches.
129 Debugger::InterruptSessionStarted(nullptr, msg.c_str());
132 // Blocking until Ctrl-C is issued by end user and DebuggerProxy cannot
133 // find a real sandbox thread to handle it.
135 Lock lock(this);
136 while (!m_stopped && m_signum != CmdSignal::SignalBreak) {
137 wait(1);
139 if (m_stopped) {
140 // stopped by worker thread
141 break;
143 m_signum = CmdSignal::SignalNone;
145 } catch (const DebuggerClientExitException &e) {
146 // stopped by the dummy sandbox thread itself
147 break;
148 } catch (const DebuggerException &e) {
153 void DummySandbox::notifySignal(int signum) {
154 TRACE(2, "DummySandbox::notifySignal\n");
155 Lock lock(this);
156 m_signum = signum;
157 notify();
160 std::string DummySandbox::getStartupDoc(const DSandboxInfo &sandbox) {
161 TRACE(2, "DummySandbox::getStartupDoc\n");
162 string path;
163 if (!m_startupFile.empty()) {
164 // if relative path, prepend directory
165 if (m_startupFile[0] != '/' && m_startupFile[0] != '~') {
166 path = sandbox.m_path;
167 if (path.empty()) {
168 path = m_defaultPath;
171 if (!path.empty() && path[path.size() - 1] != '/') {
172 path += '/';
174 path += m_startupFile;
176 // resolving home directory
177 if (path[0] == '~') {
178 string user, home;
179 size_t pos = path.find('/');
180 if (pos == string::npos) pos = path.size();
181 if (pos > 1) {
182 user = path.substr(1, pos - 1);
184 if (user.empty()) user = sandbox.m_user;
185 if (user.empty() || user == Process::GetCurrentUser()) {
186 home = Process::GetHomeDirectory();
187 } else {
188 home = "/home/" + user + "/";
190 if (pos + 1 < path.size()) {
191 path = home + path.substr(pos + 1);
192 } else {
193 path = home;
197 return path;
200 ///////////////////////////////////////////////////////////////////////////////