Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fetch constants + set flags.

  • Loading branch information...
commit 8914df9aa56ec2f1072419539a2b91a2e51910de 1 parent 0a9574b
@jarib authored
View
17 Rakefile
@@ -50,10 +50,13 @@ task :jar => [:clean, :build] do
sh "jar tf childprocess.jar"
end
-namespace :generate do
- desc 'Calculate size of posix_spawn structs for the current platform'
- task :sizes do
- require './lib/childprocess/tools/sizeof.rb'
- ChildProcess::Tools::SizeOf.generate
- end
-end
+task :env do
+ $:.unshift File.expand_path("../lib", __FILE__)
+ require 'childprocess'
+end
+
+desc 'Calculate size of posix_spawn structs for the current platform'
+task :generate => :env do
+ require 'childprocess/tools/generator'
+ ChildProcess::Tools::Generator.generate
+end
View
2  lib/childprocess.rb
@@ -63,7 +63,7 @@ def posix_spawn?
require 'ffi'
begin
- require "childprocess/unix/platform/#{FFI::Platform::NAME}/sizes"
+ require "childprocess/unix/platform/#{FFI::Platform::NAME}"
rescue LoadError
raise ChildProcess::MissingPlatformError
end
View
139 lib/childprocess/tools/generator.rb
@@ -0,0 +1,139 @@
+require 'ffi'
+require 'fileutils'
+
+module ChildProcess
+ module Tools
+ class Generator
+ EXE_NAME = "childprocess-sizeof-generator"
+ TMP_PROGRAM = "childprocess-sizeof-generator.c"
+ DEFAULT_INCLUDES = %w[stdio.h stddef.h]
+
+ def self.generate
+ new.generate
+ end
+
+ def initialize
+ @cc = ENV['CC'] || 'gcc'
+ @out = File.expand_path("../../unix/platform/#{FFI::Platform::NAME}.rb", __FILE__)
+ @sizeof = {}
+ @constants = {}
+ end
+
+ def generate
+ fetch_size 'posix_spawn_file_actions_t', :include => "spawn.h"
+ fetch_size 'posix_spawnattr_t', :include => "spawn.h"
+
+ fetch_constant 'POSIX_SPAWN_RESETIDS', :include => 'spawn.h'
+ fetch_constant 'POSIX_SPAWN_SETPGROUP', :include => 'spawn.h'
+ fetch_constant 'POSIX_SPAWN_SETSIGDEF', :include => 'spawn.h'
+ fetch_constant 'POSIX_SPAWN_SETSIGMASK', :include => 'spawn.h'
+
+ if ChildProcess.os == :linux
+ fetch_constant 'POSIX_SPAWN_USEVFORK', :include => 'spawn.h', :define => {'_GNU_SOURCE' => nil}
+ end
+
+ write
+ end
+
+ def write
+ FileUtils.mkdir_p(File.dirname(@out))
+ File.open(@out, 'w') do |io|
+ io.puts result
+ end
+
+ puts "wrote #{@out}"
+ end
+
+ def fetch_size(type_name, opts = {})
+ src = <<-EOF
+int main() {
+ printf("%d", (unsigned int)sizeof(#{type_name}));
+ return 0;
+}
+ EOF
+
+ output = execute(src, opts)
+
+ if output.to_i < 1
+ raise "sizeof(#{type_name}) == #{output.to_i} (output=#{output})"
+ end
+
+ @sizeof[type_name] = output.to_i
+ end
+
+ def fetch_constant(name, opts)
+ src = <<-EOF
+int main() {
+ printf("%d", (unsigned int)#{name});
+ return 0;
+}
+ EOF
+
+ output = execute(src, opts)
+ @constants[name] = Integer(output)
+ end
+
+
+ def execute(src, opts)
+
+ program = Array(opts[:define]).map do |key, value|
+ <<-SRC
+#ifndef #{key}
+#define #{key} #{value}
+#endif
+ SRC
+ end.join("\n")
+ program << "\n"
+
+ includes = Array(opts[:include]) + DEFAULT_INCLUDES
+ program << includes.map { |include| "#include <#{include}>" }.join("\n")
+ program << "\n#{src}"
+
+ File.open(TMP_PROGRAM, 'w') do |file|
+ file << program
+ end
+
+ cmd = "#{@cc} #{TMP_PROGRAM} -o #{EXE_NAME}"
+ system cmd
+ unless $?.success?
+ raise "failed to compile program: #{cmd.inspect}\n#{program}"
+ end
+
+ output = `./#{EXE_NAME} 2>&1`
+
+ unless $?.success?
+ raise "failed to run program: #{cmd.inspect}\n#{output}"
+ end
+
+ output.chomp
+ ensure
+ File.delete TMP_PROGRAM if File.exist?(TMP_PROGRAM)
+ File.delete EXE_NAME if File.exist?(EXE_NAME)
+ end
+
+ def result
+ if @sizeof.empty?
+ raise "no sizes collected, nothing to do"
+ end
+
+ out = ['module ChildProcess::Unix::Platform']
+ out << ' SIZEOF = {'
+
+ max = @sizeof.keys.map { |e| e.length }.max
+ @sizeof.each_with_index do |(type, size), idx|
+ out << " :#{type.ljust max} => #{size}#{',' unless idx == @sizeof.size - 1}"
+ end
+ out << ' }'
+
+ max = @constants.keys.map { |e| e.length }.max
+ @constants.each do |name, val|
+ out << " #{name.ljust max} = #{val}"
+ end
+ out << 'end'
+
+ out.join "\n"
+ end
+
+ end
+ end
+end
View
93 lib/childprocess/tools/sizeof.rb
@@ -1,93 +0,0 @@
-require 'ffi'
-require 'fileutils'
-
-module ChildProcess
- module Tools
- class SizeOf
- EXE_NAME = "childprocess-sizeof-generator"
- TMP_PROGRAM = "childprocess-sizeof-generator.c"
-
- def self.generate
- new.generate
- end
-
- def initialize
- @cc = ENV['CC'] || 'gcc'
- @out = File.expand_path("../../unix/platform/#{FFI::Platform::NAME}/sizes.rb", __FILE__)
- @sizeof = {}
- end
-
- def generate
- fetch_size 'posix_spawn_file_actions_t', "spawn.h"
- fetch_size 'posix_spawnattr_t', "spawn.h"
-
- write
- end
-
- def write
- FileUtils.mkdir_p(File.dirname(@out))
- File.open(@out, 'w') do |io|
- io.puts result
- end
-
- puts "wrote #{@out}"
- end
-
- def fetch_size(type_name, includes = nil)
- src = Array(includes).map { |include| "#include <#{include}>" }.join("\n")
- src += <<-EOF
-
-#include <stdio.h>
-#include <stddef.h>
-int main() {
- printf("%d", (unsigned int)sizeof(#{type_name}));
- return 0;
-}
- EOF
-
- File.open(TMP_PROGRAM, 'w') do |file|
- file << src
- end
-
- cmd = "#{@cc} #{TMP_PROGRAM} -o #{EXE_NAME}"
- system cmd
- unless $?.success?
- raise "failed to compile program: #{cmd.inspect}\n#{src}"
- end
-
- output = `./#{EXE_NAME} 2>&1`
-
- unless $?.success?
- raise "failed to run program: #{cmd.inspect}\n#{output}"
- end
-
- if output.to_i < 1
- raise "sizeof(#{type_name}) == #{output.to_i} (output=#{output})"
- end
-
- @sizeof[type_name] = output.to_i
- ensure
- File.delete TMP_PROGRAM if File.exist?(TMP_PROGRAM)
- File.delete EXE_NAME if File.exist?(EXE_NAME)
- end
-
- def result
- if @sizeof.empty?
- raise "no sizes collected, nothing to do"
- end
-
- out = ['module ChildProcess::Unix::Platform']
- out << ' SIZEOF = {'
- @sizeof.each_with_index do |(type, size), idx|
- out << " :#{type} => #{size}#{',' unless idx == @sizeof.size - 1}"
- end
-
- out << ' }'
- out << 'end'
-
- out.join "\n"
- end
-
- end
- end
-end
View
37 lib/childprocess/unix/lib.rb
@@ -88,20 +88,20 @@ def self.check(errno)
class FileActions
def initialize
- @data = FFI::MemoryPointer.new(1, Platform::SIZEOF.fetch(:posix_spawn_file_actions_t), false)
- Lib.check Lib.posix_spawn_file_actions_init(@data)
+ @ptr = FFI::MemoryPointer.new(1, Platform::SIZEOF.fetch(:posix_spawn_file_actions_t), false)
+ Lib.check Lib.posix_spawn_file_actions_init(@ptr)
end
def add_close(fileno)
Lib.check Lib.posix_spawn_file_actions_addclose(
- @data,
+ @ptr,
fileno
)
end
def add_open(fileno, path, oflag, mode)
Lib.check Lib.posix_spawn_file_actions_addopen(
- @data,
+ @ptr,
fileno,
path,
oflag,
@@ -111,35 +111,46 @@ def add_open(fileno, path, oflag, mode)
def add_dup(fileno, new_fileno)
Lib.check Lib.posix_spawn_file_actions_adddup2(
- @data,
+ @ptr,
fileno,
new_fileno
)
end
def free
- Lib.check Lib.posix_spawn_file_actions_destroy(@data)
- @data = nil
+ Lib.check Lib.posix_spawn_file_actions_destroy(@ptr)
+ @ptr = nil
end
def to_ptr
- @data
+ @ptr
end
end # FileActions
class Attrs
def initialize
- @data = FFI::MemoryPointer.new(1, Platform::SIZEOF.fetch(:posix_spawnattr_t), false)
- Lib.check Lib.posix_spawnattr_init(@data)
+ @ptr = FFI::MemoryPointer.new(1, Platform::SIZEOF.fetch(:posix_spawnattr_t), false)
+ Lib.check Lib.posix_spawnattr_init(@ptr)
end
def free
- Lib.check Lib.posix_spawnattr_destroy(@data)
- @data = nil
+ Lib.check Lib.posix_spawnattr_destroy(@ptr)
+ @ptr = nil
+ end
+
+ def flags=(flags)
+ Lib.check Lib.posix_spawnattr_setflags(@ptr, flags)
+ end
+
+ def flags
+ ptr = FFI::MemoryPointer.new(:short)
+ Lib.check Lib.posix_spawnattr_getflags(@ptr, ptr)
+
+ ptr.read_short
end
def to_ptr
- @data
+ @ptr
end
end # Attrs
View
11 lib/childprocess/unix/platform/i386-linux.rb
@@ -0,0 +1,11 @@
+module ChildProcess::Unix::Platform
+ SIZEOF = {
+ :posix_spawn_file_actions_t => 76,
+ :posix_spawnattr_t => 336
+ }
+ POSIX_SPAWN_RESETIDS = 1
+ POSIX_SPAWN_SETPGROUP = 2
+ POSIX_SPAWN_SETSIGDEF = 4
+ POSIX_SPAWN_SETSIGMASK = 8
+ POSIX_SPAWN_USEVFORK = 64
+end
View
6 lib/childprocess/unix/platform/i386-linux/sizes.rb
@@ -1,6 +0,0 @@
-module ChildProcess::Unix::Platform
- SIZEOF = {
- :posix_spawn_file_actions_t => 76,
- :posix_spawnattr_t => 336
- }
-end
View
10 lib/childprocess/unix/platform/x86_64-darwin.rb
@@ -0,0 +1,10 @@
+module ChildProcess::Unix::Platform
+ SIZEOF = {
+ :posix_spawn_file_actions_t => 8,
+ :posix_spawnattr_t => 8
+ }
+ POSIX_SPAWN_RESETIDS = 1
+ POSIX_SPAWN_SETPGROUP = 2
+ POSIX_SPAWN_SETSIGDEF = 4
+ POSIX_SPAWN_SETSIGMASK = 8
+end
View
6 lib/childprocess/unix/platform/x86_64-darwin/sizes.rb
@@ -1,6 +0,0 @@
-module ChildProcess::Unix::Platform
- SIZEOF = {
- :posix_spawn_file_actions_t => 8,
- :posix_spawnattr_t => 8
- }
-end
View
6 lib/childprocess/unix/platform/x86_64-linux/sizes.rb
@@ -1,6 +0,0 @@
-module ChildProcess::Unix::Platform
- SIZEOF = {
- :posix_spawn_file_actions_t => 80,
- :posix_spawnattr_t => 336
- }
-end
View
12 lib/childprocess/unix/posix_spawn_process.rb
@@ -11,9 +11,9 @@ def initialize(args)
def launch_process
pid_ptr = FFI::MemoryPointer.new(:pid_t)
-
actions = Lib::FileActions.new
- attrs = nil # Lib::Attrs.new
+ attrs = Lib::Attrs.new
+ flags = 0
if @io
if @io.stdout
@@ -35,6 +35,12 @@ def launch_process
actions.add_close writer.fileno
end
+ if defined?(Platform::POSIX_SPAWN_USEVFORK)
+ flags |= Platform::POSIX_SPAWN_USEVFORK
+ end
+
+ attrs.flags = flags
+
ret = Lib.posix_spawnp(
pid_ptr,
@args.first, # TODO: pass to /bin/sh if this is the only arg?
@@ -50,7 +56,7 @@ def launch_process
end
actions.free
- # attrs.free
+ attrs.free
if ret != 0
raise LaunchError, "#{Lib.strerror(ret)} (#{ret})"
Please sign in to comment.
Something went wrong with that request. Please try again.