Class: CommandRunner

Inherits:
Object show all
Defined in:
lib/carat-dev/commandrunner/commandrunner.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*command) ⇒ CommandRunner

Returns a new instance of CommandRunner.



5
6
7
8
9
10
11
12
13
# File 'lib/carat-dev/commandrunner/commandrunner.rb', line 5

def initialize(*command)
    @command        = command
    @child_pid      = nil
    @waiting_thread = nil

    @read_pipe        = nil
    @read_error_pipe  = nil
    @write_pipe       = nil
end

Instance Attribute Details

#child_pidObject (readonly)

Returns the value of attribute child_pid.



3
4
5
# File 'lib/carat-dev/commandrunner/commandrunner.rb', line 3

def child_pid
  @child_pid
end

#commandObject (readonly)

Returns the value of attribute command.



2
3
4
# File 'lib/carat-dev/commandrunner/commandrunner.rb', line 2

def command
  @command
end

Instance Method Details

#closeWriteObject



15
16
17
# File 'lib/carat-dev/commandrunner/commandrunner.rb', line 15

def closeWrite
    @write_pipe.close
end

#killObject



19
20
21
# File 'lib/carat-dev/commandrunner/commandrunner.rb', line 19

def kill
    Process.kill("KILL", @child_pid)
end

#readObject



23
24
25
# File 'lib/carat-dev/commandrunner/commandrunner.rb', line 23

def read
    return @read_pipe.read
end

#readErrorObject



27
28
29
# File 'lib/carat-dev/commandrunner/commandrunner.rb', line 27

def readError
    return @read_error_pipe.read
end

#runObject



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/carat-dev/commandrunner/commandrunner.rb', line 31

def run
    parent_to_child_read, parent_to_child_write             = IO.pipe
    child_to_parent_read, child_to_parent_write             = IO.pipe
    child_to_parent_error_read, child_to_parent_error_write = IO.pipe

    @child_pid = fork do
        parent_to_child_write.close
        child_to_parent_read.close
        child_to_parent_error_read.close

        # Wait until parent is ready before we start doing anything
        if parent_to_child_read.readchar.chr != "R"
            raise "Unexpected input from parent"
        end

        $stdin.reopen(parent_to_child_read)
        $stdout.reopen(child_to_parent_write)
        $stderr.reopen(child_to_parent_error_write)

        exec(*@command)
    end

    @waiting_thread = Thread.new(@child_pid) do |pid|
        return_code = -1

        begin
            return_code = Process.waitpid2(pid)
        rescue SystemError
            raise "Process finished running already!"
        end
        return_code = return_code[1].exitstatus

        return_code
    end

    child_to_parent_write.close
    child_to_parent_error_write.close
    parent_to_child_read.close

    @read_pipe        = child_to_parent_read
    @read_error_pipe  = child_to_parent_error_read
    @write_pipe       = parent_to_child_write

    @write_pipe.write("R")
    @write_pipe.flush
end

#waitObject


Waits for command to exit Returns: The return code of the program when it exited




82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/carat-dev/commandrunner/commandrunner.rb', line 82

def wait
    if not @child_pid or not @waiting_thread
        raise "Waiting for a process that has not started"
    end

    return_value = @waiting_thread.value

    @waiting_thread = nil
    @child_pid = nil

    return return_value
end

#write(string) ⇒ Object



95
96
97
# File 'lib/carat-dev/commandrunner/commandrunner.rb', line 95

def write(string)
    @write_pipe.write(string)
end