Skip to contentSkip to conversation

test/py: handle exceptions in console creation

PATCH In review Stephen Warren 3 participants 4 messages Feb 10, 2016 – Feb 15, 2016

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 test/py: handle exceptions in console creation

From: Stephen Warren <[email protected]>

u_boot_console.exec_attach.get_spawn() performs two steps:
1) Spawn a process to communicate with the serial console.
2) Reset the board so that U-Boot starts running from scratch.

Currently, if an exception happens in step (2), no cleanup is performed on the process created in step (1). That process stays running and may e.g. hold serial port locks, or simply continue to read data from the serial port, thus preventing it from reaching any other process that attempts to read from the same serial port later. While there is error cleanup code in u_boot_console_base.ensure_spawned(), this is not triggered since the exception prevents assignment to self.p there, and hence the exception handler has no object to operate upon in cleanup_spawn().

Solve this by enhancing u_boot_console.exec_attach.get_spawn() to clean up any objects it has created.

In theory, u_boot_spawn.Spawn's constructor has a similar issue, so fix this too.

---
 test/py/u_boot_console_exec_attach.py | 14 +++++++++-----
 test/py/u_boot_spawn.py               |  8 ++++++--
 2 files changed, 15 insertions(+), 7 deletions(-)
test/py/u_boot_console_exec_attach.py +9 -5
index 1be27c193079..445b58dda612 100644
@@ -58,10 +58,14 @@ class ConsoleExecAttach(ConsoleBase):
         args = [self.config.board_type, self.config.board_identity]
         s = Spawn(['u-boot-test-console'] + args)
 
-        self.log.action('Resetting board')
-        cmd = ['u-boot-test-reset'] + args
-        runner = self.log.get_runner(cmd[0], sys.stdout)
-        runner.run(cmd)
-        runner.close()
+        try:
+            self.log.action('Resetting board')
+            cmd = ['u-boot-test-reset'] + args
+            runner = self.log.get_runner(cmd[0], sys.stdout)
+            runner.run(cmd)
+            runner.close()
+        except:
+            s.close()
+            raise
 
         return s
test/py/u_boot_spawn.py +6 -2
index 3d9cde5ee0d0..a5f4a8e91bae 100644
@@ -56,8 +56,12 @@ class Spawn(object):
             finally:
                 os._exit(255)
 
-        self.poll = select.poll()
-        self.poll.register(self.fd, select.POLLIN | select.POLLPRI | select.POLLERR | select.POLLHUP | select.POLLNVAL)
+        try:
+            self.poll = select.poll()
+            self.poll.register(self.fd, select.POLLIN | select.POLLPRI | select.POLLERR | select.POLLHUP | select.POLLNVAL)
+        except:
+            self.close()
+            raise
 
     def kill(self, sig):
         """Send unix signal "sig" to the child process.
Signature · 1 line
2.7.0
#1 lore raw

PATCH 1/1 test/py: handle exceptions in console creation

Hi Stephen,

Quoted 18 lines · Stephen Warren

From: Stephen Warren <[email protected]>

u_boot_console.exec_attach.get_spawn() performs two steps:
1) Spawn a process to communicate with the serial console.
2) Reset the board so that U-Boot starts running from scratch.

Currently, if an exception happens in step (2), no cleanup is performed on the process created in step (1). That process stays running and may e.g. hold serial port locks, or simply continue to read data from the serial port, thus preventing it from reaching any other process that attempts to read from the same serial port later. While there is error cleanup code in u_boot_console_base.ensure_spawned(), this is not triggered since the exception prevents assignment to self.p there, and hence the exception handler has no object to operate upon in cleanup_spawn().

Solve this by enhancing u_boot_console.exec_attach.get_spawn() to clean up any objects it has created.

Quoted 9 lines

In theory, u_boot_spawn.Spawn's constructor has a similar issue, so fix this too.

---
 test/py/u_boot_console_exec_attach.py | 14 +++++++++-----
 test/py/u_boot_spawn.py               |  8 ++++++--
 2 files changed, 15 insertions(+), 7 deletions(-)

But please see below.

Quoted 12 lines
test/py/u_boot_console_exec_attach.py +0 -4
index 1be27c193079..445b58dda612 100644
@@ -58,10 +58,14 @@ class ConsoleExecAttach(ConsoleBase):
         args = [self.config.board_type, self.config.board_identity]
         s = Spawn(['u-boot-test-console'] + args)
 
-        self.log.action('Resetting board')
-        cmd = ['u-boot-test-reset'] + args
-        runner = self.log.get_runner(cmd[0], sys.stdout)
-        runner.run(cmd)

test/py/u_boot_console_exec_attach.py class ConsoleExecAttach(ConsoleBase): · line 69

Quoted 10 lines
test/py/u_boot_console_exec_attach.py +9 -1
-        runner.close()
+        try:
+            self.log.action('Resetting board')
+            cmd = ['u-boot-test-reset'] + args
+            runner = self.log.get_runner(cmd[0], sys.stdout)
+            runner.run(cmd)
+            runner.close()
+        except:
+            s.close()
+            raise

Would try...finally work here? It might avoid the 'raise'.

Quoted 24 lines
test/py/u_boot_console_exec_attach.py +0 -0
         return s
test/py/u_boot_spawn.py +6 -3
index 3d9cde5ee0d0..a5f4a8e91bae 100644
@@ -56,8 +56,12 @@ class Spawn(object):
             finally:
                 os._exit(255)
 
-        self.poll = select.poll()
-        self.poll.register(self.fd, select.POLLIN | select.POLLPRI | select.POLLERR | select.POLLHUP | select.POLLNVAL)
+        try:
+            self.poll = select.poll()
+            self.poll.register(self.fd, select.POLLIN | select.POLLPRI | select.POLLERR | select.POLLHUP | select.POLLNVAL)
+        except:
+            self.close()
+            raise
 
     def kill(self, sig):
         """Send unix signal "sig" to the child process.
--

2.7.0

#2 lore raw

PATCH 1/1 test/py: handle exceptions in console creation

Quoted 43 lines · Simon Glass

Hi Stephen,

Quoted 18 lines · Stephen Warren

From: Stephen Warren <[email protected]>

u_boot_console.exec_attach.get_spawn() performs two steps:
1) Spawn a process to communicate with the serial console.
2) Reset the board so that U-Boot starts running from scratch.

Currently, if an exception happens in step (2), no cleanup is performed on the process created in step (1). That process stays running and may e.g. hold serial port locks, or simply continue to read data from the serial port, thus preventing it from reaching any other process that attempts to read from the same serial port later. While there is error cleanup code in u_boot_console_base.ensure_spawned(), this is not triggered since the exception prevents assignment to self.p there, and hence the exception handler has no object to operate upon in cleanup_spawn().

Solve this by enhancing u_boot_console.exec_attach.get_spawn() to clean up any objects it has created.

Quoted 9 lines

In theory, u_boot_spawn.Spawn's constructor has a similar issue, so fix this too.

---
 test/py/u_boot_console_exec_attach.py | 14 +++++++++-----
 test/py/u_boot_spawn.py               |  8 ++++++--
 2 files changed, 15 insertions(+), 7 deletions(-)

But please see below.

Quoted 8 lines
test/py/u_boot_console_exec_attach.py +0 -0
index 1be27c193079..445b58dda612 100644
@@ -58,10 +58,14 @@ class ConsoleExecAttach(ConsoleBase):
         args = [self.config.board_type, self.config.board_identity]
         s = Spawn(['u-boot-test-console'] + args)
 
Quoted 16 lines
Quoted 4 lines
test/py/u_boot_console_exec_attach.py +0 -4
-        self.log.action('Resetting board')
-        cmd = ['u-boot-test-reset'] + args
-        runner = self.log.get_runner(cmd[0], sys.stdout)
-        runner.run(cmd)

test/py/u_boot_console_exec_attach.py class ConsoleExecAttach(ConsoleBase): · line 69

Quoted 10 lines
test/py/u_boot_console_exec_attach.py +9 -1
-        runner.close()
+        try:
+            self.log.action('Resetting board')
+            cmd = ['u-boot-test-reset'] + args
+            runner = self.log.get_runner(cmd[0], sys.stdout)
+            runner.run(cmd)
+            runner.close()
+        except:
+            s.close()
+            raise

Would try...finally work here? It might avoid the 'raise'.

In the non-error case, s is returned later in the function and continues to be used by the caller. So, we don't want to tear it down except when an exception occurred.

#3 lore raw
In reply to Stephen Warren
Quoted 15 lines · Stephen Warren

From: Stephen Warren <[email protected]>

u_boot_console.exec_attach.get_spawn() performs two steps:
1) Spawn a process to communicate with the serial console.
2) Reset the board so that U-Boot starts running from scratch.

Currently, if an exception happens in step (2), no cleanup is performed on the process created in step (1). That process stays running and may e.g. hold serial port locks, or simply continue to read data from the serial port, thus preventing it from reaching any other process that attempts to read from the same serial port later. While there is error cleanup code in u_boot_console_base.ensure_spawned(), this is not triggered since the exception prevents assignment to self.p there, and hence the exception handler has no object to operate upon in cleanup_spawn().

Quoted 8 lines

Solve this by enhancing u_boot_console.exec_attach.get_spawn() to clean up any objects it has created.

In theory, u_boot_spawn.Spawn's constructor has a similar issue, so fix this too.

Applied to u-boot/master, thanks!

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160215/1182f35f/attachment.sig>