Module: PhusionPassenger::NativeSupport
- Defined in:
- ext/ruby/passenger_native_support.c
Defined Under Namespace
Classes: FileSystemWatcher
Constant Summary collapse
- UNIX_PATH_MAX =
The maximum length of a Unix socket path, including terminating null.
INT2NUM(sizeof(addr.sun_path))
- SSIZE_MAX =
The maximum size of the data that may be passed to #writev.
LL2NUM(SSIZE_MAX)
Class Method Summary collapse
- .detach_process(pid) ⇒ Object
-
.disable_stdio_buffering ⇒ Object
Disables any kind of buffering on the C
stdout
andstderr
variables, so that fprintf() onstdout
andstderr
have immediate effect. -
.freeze_process ⇒ Object
Freeze the current process forever.
- .process_times ⇒ Object
-
.split_by_null_into_hash(data) ⇒ Object
Split the given string into an hash.
-
.writev(fd, components) ⇒ Object
Writes all of the strings in the
components
array into the given file descriptor using the writev() system call. -
.writev2(fd, components1, components2) ⇒ Object
Like #writev, but accepts two arrays.
-
.writev3(fd, components1, components2, components3) ⇒ Object
Like #writev, but accepts three arrays.
Class Method Details
.detach_process(pid) ⇒ Object
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 |
# File 'ext/ruby/passenger_native_support.c', line 417
static VALUE
detach_process(VALUE self, VALUE pid) {
pthread_t thr;
pthread_attr_t attr;
size_t stack_size = 96 * 1024;
unsigned long min_stack_size;
int stack_min_size_defined;
int round_stack_size;
#ifdef PTHREAD_STACK_MIN
// PTHREAD_STACK_MIN may not be a constant macro so we need
// to evaluate it dynamically.
min_stack_size = PTHREAD_STACK_MIN;
stack_min_size_defined = 1;
#else
// Assume minimum stack size is 128 KB.
min_stack_size = 128 * 1024;
stack_min_size_defined = 0;
#endif
if (stack_size != 0 && stack_size < min_stack_size) {
stack_size = min_stack_size;
round_stack_size = !stack_min_size_defined;
} else {
round_stack_size = 1;
}
if (round_stack_size) {
// Round stack size up to page boundary.
long page_size;
#if defined(_SC_PAGESIZE)
page_size = sysconf(_SC_PAGESIZE);
#elif defined(_SC_PAGE_SIZE)
page_size = sysconf(_SC_PAGE_SIZE);
#elif defined(PAGESIZE)
page_size = sysconf(PAGESIZE);
#elif defined(PAGE_SIZE)
page_size = sysconf(PAGE_SIZE);
#else
page_size = getpagesize();
#endif
if (stack_size % page_size != 0) {
stack_size = stack_size - (stack_size % page_size) + page_size;
}
}
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, 1);
pthread_attr_setstacksize(&attr, stack_size);
pthread_create(&thr, &attr, detach_process_main, (void *) NUM2LONG(pid));
pthread_attr_destroy(&attr);
return Qnil;
}
|
.disable_stdio_buffering ⇒ Object
Disables any kind of buffering on the C stdout
and stderr
variables, so that fprintf() on stdout
and stderr
have immediate effect.
98 99 100 101 102 103 |
# File 'ext/ruby/passenger_native_support.c', line 98 static VALUE disable_stdio_buffering(VALUE self) { setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); return Qnil; } |
.freeze_process ⇒ Object
Freeze the current process forever. On Ruby 1.9 this never unlocks the GIL. Useful for testing purposes.
475 476 477 478 479 480 481 |
# File 'ext/ruby/passenger_native_support.c', line 475
static VALUE
freeze_process(VALUE self) {
while (1) {
usleep(60 * 1000000);
}
return Qnil;
}
|
.process_times ⇒ Object
393 394 395 396 397 398 399 400 401 402 403 404 405 |
# File 'ext/ruby/passenger_native_support.c', line 393
static VALUE
process_times(VALUE self) {
struct rusage usage;
unsigned long long utime, stime;
if (getrusage(RUSAGE_SELF, &usage) == -1) {
rb_sys_fail("getrusage()");
}
utime = (unsigned long long) usage.ru_utime.tv_sec * 1000000 + usage.ru_utime.tv_usec;
stime = (unsigned long long) usage.ru_stime.tv_sec * 1000000 + usage.ru_stime.tv_usec;
return rb_struct_new(S_ProcessTimes, rb_ull2inum(utime), rb_ull2inum(stime));
}
|
.split_by_null_into_hash(data) ⇒ Object
Split the given string into an hash. Keys and values are obtained by splitting the string using the null character as the delimitor.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'ext/ruby/passenger_native_support.c', line 109
static VALUE
split_by_null_into_hash(VALUE self, VALUE data) {
const char *cdata = RSTRING_PTR(data);
unsigned long len = RSTRING_LEN(data);
const char *begin = cdata;
const char *current = cdata;
const char *end = cdata + len;
VALUE result, key, value;
result = rb_hash_new();
while (current < end) {
if (*current == '\0') {
key = rb_str_substr(data, begin - cdata, current - begin);
begin = current = current + 1;
while (current < end) {
if (*current == '\0') {
value = rb_str_substr(data, begin - cdata, current - begin);;
begin = current = current + 1;
rb_hash_aset(result, key, value);
break;
} else {
current++;
}
}
} else {
current++;
}
}
return result;
}
|
.writev(fd, components) ⇒ Object
Writes all of the strings in the components
array into the given file descriptor using the writev() system call. Unlike IO#write, this method does not require one to concatenate all those strings into a single buffer in order to send the data in a single system call. Thus, #writev is a great way to perform zero-copy I/O.
Unlike the raw writev() system call, this method ensures that all given data is written before returning, by performing multiple writev() calls and whatever else is necessary.
writev(@socket.fileno, ["hello ", "world", "\n"])
363 364 365 366 |
# File 'ext/ruby/passenger_native_support.c', line 363
static VALUE
f_writev(VALUE self, VALUE fd, VALUE components) {
return f_generic_writev(fd, &components, 1);
}
|
.writev2(fd, components1, components2) ⇒ Object
Like #writev, but accepts two arrays. The data is written in the given order.
writev2(@socket.fileno, ["hello ", "world", "\n"], ["another ", "message\n"])
373 374 375 376 377 |
# File 'ext/ruby/passenger_native_support.c', line 373
static VALUE
f_writev2(VALUE self, VALUE fd, VALUE components1, VALUE components2) {
VALUE array_of_components[2] = { components1, components2 };
return f_generic_writev(fd, array_of_components, 2);
}
|
.writev3(fd, components1, components2, components3) ⇒ Object
Like #writev, but accepts three arrays. The data is written in the given order.
writev3(@socket.fileno,
["hello ", "world", "\n"],
["another ", "message\n"],
["yet ", "another ", "one", "\n"])
387 388 389 390 391 |
# File 'ext/ruby/passenger_native_support.c', line 387
static VALUE
f_writev3(VALUE self, VALUE fd, VALUE components1, VALUE components2, VALUE components3) {
VALUE array_of_components[3] = { components1, components2, components3 };
return f_generic_writev(fd, array_of_components, 3);
}
|