]>
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
, cwd
=None):
24 """Spawn (fork/exec) the sub-process.
27 args: array of processs arguments. argv[0] is the command to
29 cwd: the directory to run the process in, or None for no change.
37 self
.logfile_read
= None
42 (self
.pid
, self
.fd
) = pty
.fork()
45 # For some reason, SIGHUP is set to SIG_IGN at this point when
46 # run under "go" (www.go.cd). Perhaps this happens under any
47 # background (non-interactive) system?
48 signal
.signal(signal
.SIGHUP
, signal
.SIG_DFL
)
51 os
.execvp(args
[0], args
)
53 print 'CHILD EXECEPTION:'
60 self
.poll
= select
.poll()
61 self
.poll
.register(self
.fd
, select
.POLLIN | select
.POLLPRI | select
.POLLERR | select
.POLLHUP | select
.POLLNVAL
)
67 """Send unix signal "sig" to the child process.
70 sig: The signal number to send.
76 os
.kill(self
.pid
, sig
)
79 """Determine whether the child process is still running.
85 Boolean indicating whether process is alive.
91 w
= os
.waitpid(self
.pid
, os
.WNOHANG
)
99 """Send data to the sub-process's stdin.
102 data: The data to send to the process.
108 os
.write(self
.fd
, data
)
110 def expect(self
, patterns
):
111 """Wait for the sub-process to emit specific data.
113 This function waits for the process to emit one pattern from the
114 supplied list of patterns, or for a timeout to occur.
117 patterns: A list of strings or regex objects that we expect to
118 see in the sub-process' stdout.
121 The index within the patterns array of the pattern the process
125 Timeout, if the process did not emit any of the patterns within
129 for pi
in xrange(len(patterns
)):
130 if type(patterns
[pi
]) == type(''):
131 patterns
[pi
] = re
.compile(patterns
[pi
])
133 tstart_s
= time
.time()
138 for pi
in xrange(len(patterns
)):
139 pattern
= patterns
[pi
]
140 m
= pattern
.search(self
.buf
)
143 if earliest_m
and m
.start() >= earliest_m
.start():
148 pos
= earliest_m
.start()
149 posafter
= earliest_m
.end()
150 self
.before
= self
.buf
[:pos
]
151 self
.after
= self
.buf
[pos
:posafter
]
152 self
.buf
= self
.buf
[posafter
:]
156 tdelta_ms
= (tnow_s
- tstart_s
) * 1000
157 poll_maxwait
= self
.timeout
- tdelta_ms
158 if tdelta_ms
> self
.timeout
:
162 events
= self
.poll
.poll(poll_maxwait
)
165 c
= os
.read(self
.fd
, 1024)
168 if self
.logfile_read
:
169 self
.logfile_read
.write(c
)
172 if self
.logfile_read
:
173 self
.logfile_read
.flush()
176 """Close the stdio connection to the sub-process.
178 This also waits a reasonable time for the sub-process to stop running.
188 for i
in xrange(100):
189 if not self
.isalive():