]>
git.ipfire.org Git - people/ms/u-boot.git/blob - test/py/u_boot_spawn.py
1 # Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
3 # SPDX-License-Identifier: GPL-2.0
5 # Logic to spawn a sub-process and interact with its stdio.
14 class Timeout(Exception):
15 """An exception sub-class that indicates that a timeout occurred."""
19 """Represents the stdio of a freshly created sub-process. Commands may be
20 sent to the process, and responses waited for.
23 def __init__(self
, args
):
24 """Spawn (fork/exec) the sub-process.
27 args: array of processs arguments. argv[0] is the command to execute.
35 self
.logfile_read
= None
40 (self
.pid
, self
.fd
) = pty
.fork()
43 # For some reason, SIGHUP is set to SIG_IGN at this point when
44 # run under "go" (www.go.cd). Perhaps this happens under any
45 # background (non-interactive) system?
46 signal
.signal(signal
.SIGHUP
, signal
.SIG_DFL
)
47 os
.execvp(args
[0], args
)
49 print 'CHILD EXECEPTION:'
55 self
.poll
= select
.poll()
56 self
.poll
.register(self
.fd
, select
.POLLIN | select
.POLLPRI | select
.POLLERR | select
.POLLHUP | select
.POLLNVAL
)
59 """Send unix signal "sig" to the child process.
62 sig: The signal number to send.
68 os
.kill(self
.pid
, sig
)
71 """Determine whether the child process is still running.
77 Boolean indicating whether process is alive.
83 w
= os
.waitpid(self
.pid
, os
.WNOHANG
)
91 """Send data to the sub-process's stdin.
94 data: The data to send to the process.
100 os
.write(self
.fd
, data
)
102 def expect(self
, patterns
):
103 """Wait for the sub-process to emit specific data.
105 This function waits for the process to emit one pattern from the
106 supplied list of patterns, or for a timeout to occur.
109 patterns: A list of strings or regex objects that we expect to
110 see in the sub-process' stdout.
113 The index within the patterns array of the pattern the process
117 Timeout, if the process did not emit any of the patterns within
121 for pi
in xrange(len(patterns
)):
122 if type(patterns
[pi
]) == type(''):
123 patterns
[pi
] = re
.compile(patterns
[pi
])
125 tstart_s
= time
.time()
130 for pi
in xrange(len(patterns
)):
131 pattern
= patterns
[pi
]
132 m
= pattern
.search(self
.buf
)
135 if earliest_m
and m
.start() >= earliest_m
.start():
140 pos
= earliest_m
.start()
141 posafter
= earliest_m
.end() + 1
142 self
.before
= self
.buf
[:pos
]
143 self
.after
= self
.buf
[pos
:posafter
]
144 self
.buf
= self
.buf
[posafter
:]
147 tdelta_ms
= (tnow_s
- tstart_s
) * 1000
148 if tdelta_ms
> self
.timeout
:
150 events
= self
.poll
.poll(self
.timeout
- tdelta_ms
)
153 c
= os
.read(self
.fd
, 1024)
156 if self
.logfile_read
:
157 self
.logfile_read
.write(c
)
160 if self
.logfile_read
:
161 self
.logfile_read
.flush()
164 """Close the stdio connection to the sub-process.
166 This also waits a reasonable time for the sub-process to stop running.
176 for i
in xrange(100):
177 if not self
.isalive():