Skip to content

Commit 8e023e1

Browse files
committed
Merge remote-tracking branch 'origin' into 1.8.7
Conflicts: gems_list.txt
2 parents 524e28b + 0e2ace2 commit 8e023e1

File tree

14 files changed

+258
-185
lines changed

14 files changed

+258
-185
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
GEM
22
remote: https://rubygems.org/
33
specs:
4-
daedalus-core (0.2.0)
4+
daedalus-core (0.3.0)
55
rake (10.4.2)
66
redcard (1.1.0)
77
rubinius-ast (1.3.0)

kernel/common/type.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ def self.include_modules_from(included_module, klass)
355355
changed = true
356356
end
357357

358-
constants_changed ||= mod.constants.any?
358+
constants_changed ||= mod.constant_table.size > 0
359359
end
360360

361361
mod = mod.direct_superclass

kernel/delta/console.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
module Rubinius
22
module Console
33
class Server
4-
# The following constants are set internally:
5-
# RequestPath - the path to the console request file for this process
6-
# ResponsePath - the path to the console response file for this process
7-
84
attr_reader :inbox
95
attr_reader :outbox
106
attr_reader :thread

kernel/delta/struct.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,10 @@ def length
9292
CODE
9393

9494
begin
95-
include Module.new do
95+
mod = Module.new do
9696
module_eval code
9797
end
98+
include mod
9899
rescue SyntaxError
99100
# SyntaxError means that something is wrong with the
100101
# specialization code. Just eat the error and don't specialize.

library/rubinius/configuration.rb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,11 @@
176176
s.vm_variable "tmp", "$TMPDIR",
177177
"Default temp/fallback directory for the process"
178178

179-
s.vm_variable "fsapi.path", "$TMPDIR/$PROGRAM_NAME-$USER-$PID",
180-
"Base directory of the Rubinius File System API files"
181-
182-
s.vm_variable "fsapi.access", 0750,
183-
"Permissions on the Rubinius File System API directory"
179+
s.vm_variable "console.path", "$TMPDIR/$PROGRAM_NAME-$USER-console",
180+
"Path for Rubinius Console connection file"
184181

185182
s.vm_variable "console.access", 0660,
186-
"Permissions on the Rubinius Console files"
183+
"Permissions on the Rubinius Console connection file"
187184

188185
s.vm_variable "log", "$TMPDIR/$PROGRAM_NAME-$USER.log",
189186
"Logging facility to use: 'syslog', 'console', or path"

vm/console.cpp

Lines changed: 147 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,15 @@
2626
#include <sys/types.h>
2727

2828
#include <stdio.h>
29+
#include <libgen.h>
2930

3031
// read
3132
#include <unistd.h>
3233
#include <sys/uio.h>
3334
#include <sys/types.h>
3435

36+
#include <ostream>
37+
3538
namespace rubinius {
3639
using namespace utilities;
3740

@@ -53,37 +56,31 @@ namespace rubinius {
5356
return fd;
5457
}
5558

56-
Request::Request(STATE, Console* console)
59+
Request::Request(STATE, Console* console, Response* response)
5760
: InternalThread(state, "rbx.console.request")
5861
, console_(console)
59-
, response_(console->response())
62+
, response_(response)
6063
, enabled_(false)
6164
, fd_(-1)
6265
, fsevent_(state)
6366
{
6467
}
6568

6669
void Request::initialize(STATE) {
67-
path_ = state->shared().fsapi_path + "/console-request";
68-
console_->server_class(state)->set_const(state, state->symbol("RequestPath"),
69-
String::create(state, path_.c_str()));
70-
}
71-
72-
void Request::setup_request(STATE) {
73-
if((fd_ = open_file(state, path_)) < 0) {
70+
if((fd_ = open_file(state, console_->request_path())) < 0) {
7471
logger::error("%s: console request: unable to open file", strerror(errno));
7572
return;
7673
}
7774

7875
FSEvent* fsevent = FSEvent::create(state);
79-
fsevent->watch_file(state, fd_, path_.c_str());
76+
fsevent->watch_file(state, fd_, console_->request_path().c_str());
8077
fsevent_.set(fsevent);
8178

8279
enabled_ = true;
8380
}
8481

8582
void Request::start_thread(STATE) {
86-
setup_request(state);
83+
if(!enabled_) return;
8784

8885
InternalThread::start_thread(state);
8986
}
@@ -96,7 +93,7 @@ namespace rubinius {
9693
}
9794
}
9895

99-
void Request::close_request(STATE) {
96+
void Request::close_request() {
10097
if(fd_ > 0) {
10198
close(fd_);
10299
fd_ = -1;
@@ -106,22 +103,11 @@ namespace rubinius {
106103
void Request::stop_thread(STATE) {
107104
InternalThread::stop_thread(state);
108105

109-
close_request(state);
110-
unlink(path_.c_str());
111-
}
112-
113-
void Request::before_exec(STATE) {
114-
stop_thread(state);
115-
}
116-
117-
void Request::after_exec(STATE) {
118-
start(state);
106+
close_request();
119107
}
120108

121109
void Request::after_fork_child(STATE) {
122-
close_request(state);
123-
124-
InternalThread::after_fork_child(state);
110+
close_request();
125111
}
126112

127113
char* Request::read_request(STATE) {
@@ -182,9 +168,15 @@ namespace rubinius {
182168
Response::Response(STATE, Console* console)
183169
: InternalThread(state, "rbx.console.response")
184170
, console_(console)
171+
, inbox_(state)
172+
, outbox_(state)
185173
, fd_(-1)
186174
, request_list_(NULL)
187175
{
176+
inbox_.set(as<Channel>(
177+
console_->ruby_console()->get_ivar(state, state->symbol("@inbox"))));
178+
outbox_.set(as<Channel>(
179+
console_->ruby_console()->get_ivar(state, state->symbol("@outbox"))));
188180
}
189181

190182
Response::~Response() {
@@ -193,15 +185,11 @@ namespace rubinius {
193185
}
194186

195187
void Response::initialize(STATE) {
196-
path_ = state->shared().fsapi_path + "/console-response";
197-
console_->server_class(state)->set_const(state, state->symbol("ResponsePath"),
198-
String::create(state, path_.c_str()));
199-
200188
Thread::create(state, vm());
201189
}
202190

203191
void Response::start_thread(STATE) {
204-
if((fd_ = open_file(state, path_)) < 0) {
192+
if((fd_ = open_file(state, console_->response_path())) < 0) {
205193
logger::error("%s: console response: unable to open file", strerror(errno));
206194
return;
207195
}
@@ -218,17 +206,20 @@ namespace rubinius {
218206
void Response::wakeup(STATE) {
219207
InternalThread::wakeup(state);
220208

209+
GCTokenImpl gct;
210+
inbox_.get()->send(state, gct, String::create(state, ""), 0);
211+
221212
response_cond_.signal();
222213
}
223214

224-
void Response::close_response(STATE) {
215+
void Response::close_response() {
225216
if(fd_ > 0) {
226217
close(fd_);
227218
fd_ = -1;
228219
}
229220
}
230221

231-
void Response::clear_requests(STATE) {
222+
void Response::clear_requests() {
232223
if(request_list_) {
233224
for(RequestList::const_iterator i = request_list_->begin();
234225
i != request_list_->end();
@@ -244,25 +235,11 @@ namespace rubinius {
244235
void Response::stop_thread(STATE) {
245236
InternalThread::stop_thread(state);
246237

247-
clear_requests(state);
248-
249-
close_response(state);
250-
unlink(path_.c_str());
251-
}
252-
253-
void Response::before_exec(STATE) {
254-
stop_thread(state);
255-
}
256-
257-
void Response::after_exec(STATE) {
258-
start(state);
238+
close_response();
259239
}
260240

261241
void Response::after_fork_child(STATE) {
262-
close_response(state);
263-
clear_requests(state);
264-
265-
InternalThread::after_fork_child(state);
242+
close_response();
266243
}
267244

268245
void Response::send_request(STATE, const char* request) {
@@ -301,10 +278,8 @@ namespace rubinius {
301278
size_t pending_requests = 0;
302279
char* request = NULL;
303280

304-
Channel* inbox = as<Channel>(
305-
console_->ruby_console()->get_ivar(state, state->symbol("@inbox")));
306-
Channel* outbox = as<Channel>(
307-
console_->ruby_console()->get_ivar(state, state->symbol("@outbox")));
281+
Channel* inbox = inbox_.get();
282+
Channel* outbox = outbox_.get();
308283

309284
String* response = 0;
310285
OnStack<3> os(state, inbox, outbox, response);
@@ -352,23 +327,135 @@ namespace rubinius {
352327
}
353328
}
354329

330+
Listener::Listener(STATE, Console* console)
331+
: InternalThread(state, "rbx.console.listener")
332+
, console_(console)
333+
, fsevent_(state)
334+
, fd_(-1)
335+
{
336+
}
337+
338+
Listener::~Listener() {
339+
close(fd_);
340+
}
341+
342+
void Listener::initialize(STATE) {
343+
fd_ = ::open(console_->console_path().c_str(),
344+
O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC,
345+
state->shared().config.system_console_access.value);
346+
347+
if(fd_ < 0) {
348+
utilities::logger::error("%s: unable to open Console connection file",
349+
strerror(errno));
350+
}
351+
352+
// The umask setting will override our permissions for open().
353+
if(chmod(console_->console_path().c_str(),
354+
state->shared().config.system_console_access.value) < 0) {
355+
utilities::logger::error("%s: unable to set mode for Console connection file",
356+
strerror(errno));
357+
}
358+
359+
FSEvent* fsevent = FSEvent::create(state);
360+
fsevent->watch_file(state, fd_, console_->console_path().c_str());
361+
fsevent_.set(fsevent);
362+
}
363+
364+
void Listener::start_thread(STATE) {
365+
InternalThread::start_thread(state);
366+
}
367+
368+
void Listener::wakeup(STATE) {
369+
InternalThread::wakeup(state);
370+
371+
if(write(fd_, "\0", 1) < 0) {
372+
logger::error("%s: console: unable to wake listener thread", strerror(errno));
373+
}
374+
}
375+
376+
bool Listener::connection_initiated() {
377+
struct stat st;
378+
379+
bool req = stat(console_->request_path().c_str(), &st) == 0 && S_ISREG(st.st_mode);
380+
bool res = stat(console_->response_path().c_str(), &st) == 0 && S_ISREG(st.st_mode);
381+
382+
return req && res;
383+
}
384+
385+
void Listener::run(STATE) {
386+
while(!thread_exit_) {
387+
Object* status = fsevent_.get()->wait_for_event(state);
388+
389+
if(thread_exit_) break;
390+
391+
if(status->nil_p()) {
392+
utilities::logger::error("%s: console: listener: wait for event failed",
393+
strerror(errno));
394+
continue;
395+
}
396+
397+
if(console_->connected_p()) continue;
398+
399+
if(connection_initiated()) {
400+
console_->accept(state);
401+
}
402+
}
403+
}
404+
355405
Console::Console(STATE)
356-
: path_(std::string(state->shared().fsapi_path + "/console"))
357-
, response_(new Response(state, this))
358-
, request_(new Request(state, this))
406+
: listener_(0)
407+
, response_(0)
408+
, request_(0)
359409
, ruby_console_(state)
360410
{
361-
ruby_console_.set(server_class(state)->send(state, 0, state->symbol("new")));
411+
console_path_ = state->shared().config.system_console_path.value;
412+
413+
std::ostringstream basename;
414+
basename << state->shared().config.system_console_path.value << "-"
415+
<< state->shared().pid;
416+
417+
request_path_ = basename.str() + "-request";
418+
response_path_ = basename.str() + "-response";
419+
420+
listener_ = new Listener(state, this);
362421
}
363422

364423
Console::~Console() {
365-
delete request_;
366-
delete response_;
424+
if(listener_) delete listener_;
425+
reset();
426+
}
427+
428+
bool Console::connected_p() {
429+
return request_ && request_->enabled_p();
367430
}
368431

369432
void Console::start(STATE) {
370-
request_->start(state);
371-
response_->start(state);
433+
listener_->start(state);
434+
}
435+
436+
void Console::accept(STATE) {
437+
ruby_console_.set(server_class(state)->send(state, 0, state->symbol("new")));
438+
439+
response_ = new Response(state, this);
440+
request_ = new Request(state, this, response_);
441+
}
442+
443+
void Console::reset() {
444+
if(request_) {
445+
delete request_;
446+
request_ = 0;
447+
}
448+
449+
if(response_) {
450+
delete response_;
451+
response_ = 0;
452+
}
453+
454+
ruby_console_.set(cNil);
455+
}
456+
457+
void Console::after_fork_child(STATE) {
458+
reset();
372459
}
373460

374461
Class* Console::server_class(STATE) {

0 commit comments

Comments
 (0)