Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Allow loopback agent to bind to a TCP port

  • Loading branch information...
commit 0051012210bb00eeac948c9f45c2ba553bf54acc 1 parent b9d29f0
Evan Phoenix authored
View
5 lib/rubinius/agent.rb
@@ -63,5 +63,10 @@ def close
rescue IOError
end
end
+
+ def bind(port)
+ @encoder.write_any t[:bind, Integer(port)]
+ @decoder.read_any
+ end
end
end
View
110 vm/agent.cpp
@@ -16,9 +16,16 @@
#include "config.h"
#include "agent_components.hpp"
+#include "environment.hpp"
#include <ostream>
#include <sstream>
+#include <fstream>
+
+#ifdef __APPLE__
+#include <mach-o/dyld.h>
+#endif
+
namespace rubinius {
QueryAgent::QueryAgent(SharedState& shared, VM* state)
@@ -58,6 +65,8 @@ namespace rubinius {
}
bool QueryAgent::bind(int port) {
+ if(server_fd_ > 0) return false;
+
server_fd_ = ::socket(AF_INET, SOCK_STREAM, 0);
if(server_fd_ == -1) {
std::cerr << "[QA: Unable to create socket: " << strerror(errno) << "]\n";
@@ -100,6 +109,8 @@ namespace rubinius {
add_fd(server_fd_);
+ make_discoverable();
+
return true;
}
@@ -152,6 +163,24 @@ namespace rubinius {
encoder.write_atom("error");
return true;
+
+ // If the client ask is the loopback client, give it some extra
+ // commands.
+ } else if(client == loopback_[0]) {
+ if(cmd->equal_atom("bind")) {
+ if(val->elements()->size() == 2) {
+ bert::Value* port = val->get_element(1);
+
+ if(port->integer_p()) {
+ if(bind(port->integer())) {
+ encoder.write_atom("ok");
+ return true;
+ }
+ }
+ }
+ encoder.write_atom("error");
+ return true;
+ }
}
} else if(val->equal_atom("close")) {
encoder.write_atom("bye");
@@ -247,4 +276,85 @@ namespace rubinius {
}
}
}
+
+ static char tmp_path[PATH_MAX];
+
+ static void remove_tmp_path(void) {
+ unlink(tmp_path);
+ // Ignore any errors, this is happening at shutdown.
+ }
+
+ void QueryAgent::make_discoverable() {
+ // Create a tmp file containing the information to be used
+ // by console to find us.
+
+ const char* tmpdir = 0;
+
+ if(shared_.config.qa_tmpdir.value.size() > 0) {
+ tmpdir = shared_.config.qa_tmpdir.value.c_str();
+ } else {
+ tmpdir = getenv("TMPDIR");
+ }
+
+ if(tmpdir) {
+ std::ostringstream ss;
+ pid_t pid = getpid();
+ ss << tmpdir << "/rubinius-agent." << pid;
+
+ strcpy(tmp_path, ss.str().c_str());
+ std::ofstream stream(tmp_path);
+
+ // Couldn't open the path, for whatever reason.
+ if(!stream) return;
+
+ int argc = shared_.env()->argc();
+ char** argv = shared_.env()->argv();
+
+ if(stream) {
+ stream << pid << "\n";
+ stream << port() << "\n";
+
+ for(int i = 0; i < argc; i++) {
+ stream << argv[i] << " ";
+ }
+ stream << "\n";
+
+ char buf[PATH_MAX];
+#ifdef __APPLE__
+ uint32_t size = PATH_MAX;
+ if(_NSGetExecutablePath(buf, &size) == 0) {
+ stream << buf << "\n";
+ } else if(realpath(argv[0], buf)) {
+ stream << buf << "\n";
+ } else {
+ stream << argv[0] << "\n";
+ }
+#elif defined(__linux__)
+ {
+ std::ifstream exe("/proc/self/exe");
+ if(exe) {
+ char buf[PATH_MAX];
+ exe.get(buf, PATH_MAX);
+
+ stream << buf << "\n";
+ } else if(realpath(argv[0], buf)) {
+ stream << buf << "\n";
+ } else {
+ stream << argv[0] << "\n";
+ }
+ }
+#else
+ if(realpath(argv[0], buf)) {
+ stream << buf << "\n";
+ } else {
+ stream << argv[0] << "\n";
+ }
+#endif
+
+ stream.close();
+
+ atexit(remove_tmp_path);
+ }
+ }
+ }
}
View
3  vm/agent.hpp
@@ -69,6 +69,9 @@ namespace rubinius {
bool setup_local();
bool bind(int port);
+
+ void make_discoverable();
+
virtual void perform();
bool process_commands(int client);
};
View
5 vm/configuration.hpp
@@ -31,6 +31,7 @@ namespace rubinius {
// Query Agent
config::Integer qa_port;
config::Bool qa_verbose;
+ config::String qa_tmpdir;
// Debug
config::Bool gil_debug;
@@ -71,6 +72,7 @@ namespace rubinius {
, jit_debug(this, "jit.debug", false)
, qa_port(this, "agent.start")
, qa_verbose(this, "agent.verbose")
+ , qa_tmpdir(this, "agent.tmpdir")
, gil_debug(this, "vm.gil.debug")
, print_config(this, "config.print")
, ic_stats(this, "ic.stats")
@@ -139,6 +141,9 @@ namespace rubinius {
qa_verbose.set_description(
"Whether or not the query agent should print out status to stderr");
+ qa_tmpdir.set_description(
+ "Where to store files used to discover running query agents");
+
profile.set_description(
"Configure the system to profile ruby code");
}
View
70 vm/environment.cpp
@@ -25,10 +25,6 @@
#include <execinfo.h>
#endif
-#ifdef __APPLE__
-#include <mach-o/dyld.h>
-#endif
-
#include "signal.hpp"
#include "object_utils.hpp"
@@ -58,7 +54,7 @@ namespace rubinius {
VM::init_stack_size();
- shared = new SharedState(config, config_parser);
+ shared = new SharedState(this, config, config_parser);
state = shared->new_vm();
}
@@ -374,13 +370,6 @@ namespace rubinius {
return 0;
}
- static char tmp_path[PATH_MAX];
-
- static void remove_tmp_path(void) {
- unlink(tmp_path);
- // Ignore any errors, this is happening at shutdown.
- }
-
void Environment::start_agent(int port) {
agent = new QueryAgent(*shared, state);
if(config.qa_verbose) agent->set_verbose();
@@ -390,63 +379,6 @@ namespace rubinius {
shared->set_agent(agent);
agent->run();
- // Create a tmp file containing the information to be used
- // by console to find us.
-
- if(char* tmpdir = getenv("TMPDIR")) {
- std::ostringstream ss;
- pid_t pid = getpid();
- ss << tmpdir << "/rubinius-agent." << pid;
-
- strcpy(tmp_path, ss.str().c_str());
- std::ofstream stream(tmp_path);
-
- if(stream) {
- stream << pid << "\n";
- stream << agent->port() << "\n";
-
- for(int i = 0; i < argc_; i++) {
- stream << argv_[i] << " ";
- }
- stream << "\n";
-
- char buf[PATH_MAX];
-#ifdef __APPLE__
- uint32_t size = PATH_MAX;
- if(_NSGetExecutablePath(buf, &size) == 0) {
- stream << buf << "\n";
- } else if(realpath(argv_[0], buf)) {
- stream << buf << "\n";
- } else {
- stream << argv_[0] << "\n";
- }
-#elif defined(__linux__)
- {
- std::ifstream exe("/proc/self/exe");
- if(exe) {
- char buf[PATH_MAX];
- exe.get(buf, PATH_MAX);
-
- stream << buf << "\n";
- } else if(realpath(argv_[0], buf)) {
- stream << buf << "\n";
- } else {
- stream << argv_[0] << "\n";
- }
- }
-#else
- if(realpath(argv_[0], buf)) {
- stream << buf << "\n";
- } else {
- stream << argv_[0] << "\n";
- }
-#endif
-
- stream.close();
-
- atexit(remove_tmp_path);
- }
- }
}
/* Loads the runtime kernel files. They're stored in /kernel.
View
8 vm/environment.hpp
@@ -39,6 +39,14 @@ namespace rubinius {
Environment(int argc, char** argv);
~Environment();
+ int argc() {
+ return argc_;
+ }
+
+ char** argv() {
+ return argv_;
+ }
+
void setup_cpp_terminate();
void load_config_argv(int argc, char** argv);
View
3  vm/shared_state.cpp
@@ -114,7 +114,7 @@ namespace rubinius {
}
};
- SharedState::SharedState(Configuration& config, ConfigParser& cp)
+ SharedState::SharedState(Environment* env, Configuration& config, ConfigParser& cp)
: initialized_(false)
, signal_handler_(0)
, global_handles_(new capi::Handles)
@@ -128,6 +128,7 @@ namespace rubinius {
, timer_thread_started_(false)
, agent_(0)
, root_vm_(0)
+ , env_(env)
, om(0)
, global_cache(new GlobalCache)
, config(config)
View
8 vm/shared_state.hpp
@@ -36,6 +36,7 @@ namespace rubinius {
class InlineCacheRegistry;
class ManagedThread;
class QueryAgent;
+ class Environment;
struct Interrupts {
bool check;
@@ -91,6 +92,7 @@ namespace rubinius {
int primitive_hits_[Primitives::cTotalPrimitives];
QueryAgent* agent_;
VM* root_vm_;
+ Environment* env_;
public:
Globals globals;
@@ -104,7 +106,7 @@ namespace rubinius {
Stats stats;
public:
- SharedState(Configuration& config, ConfigParser& cp);
+ SharedState(Environment* env, Configuration& config, ConfigParser& cp);
~SharedState();
static void discard(SharedState* ss);
@@ -213,6 +215,10 @@ namespace rubinius {
QueryAgent* autostart_agent();
+ Environment* env() {
+ return env_;
+ }
+
void scheduler_loop();
void enable_preemption();
View
2  vm/test/test.hpp
@@ -21,7 +21,7 @@ class VMTest {
void create() {
config_parser = new ConfigParser;
- shared = new SharedState(config, *config_parser);
+ shared = new SharedState(0, config, *config_parser);
state = shared->new_vm();
state->initialize();
state->boot();
View
12 vm/util/bert.hpp
@@ -585,14 +585,26 @@ namespace bert {
return term_;
}
+ bool integer_p() {
+ return type_ == Integer;
+ }
+
int integer() {
return term_->integer();
}
+ bool float_p() {
+ return type_ == Float;
+ }
+
double float_number() {
return term_->float_number();
}
+ bool string_p() {
+ return type_ == Binary;
+ }
+
char* string() {
return term_->string();
}
Please sign in to comment.
Something went wrong with that request. Please try again.