aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Chan <benchan@chromium.org>2014-01-08 10:13:16 -0800
committerAleksander Morgado <aleksander@aleksander.es>2014-01-09 13:10:07 +0100
commitfd1a1839ae1bcade2f9d422f6bc0d6e6040295e6 (patch)
tree2727990afc16401770176c5ad8efdd4b760ed74f /src
parent910a55a0f2373a3469e7d0f3fe6dc5b0e8440e9f (diff)
serial-port: fail open/reopen after a serial port has been forced close
After a MMSerialPort object is forced close, it may be opened again if some other object still holds a reference to it. When the MMSerialPort object is eventually disposed, mm_serial_port_close_force is invoked on the object but does nothing as 'priv->forced_close' is already set to TRUE. 'priv->watch_id' is still active, which could potentially lead to a crash if data_available is called after the MMSerialPort object is finalized. This patch prevents such a scenario by failing mm_serial_port_open / mm_serial_port_reopen after the MMSerialPort has been forced close.
Diffstat (limited to 'src')
-rw-r--r--src/mm-serial-port.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c
index 6db2efdf..cc4fc461 100644
--- a/src/mm-serial-port.c
+++ b/src/mm-serial-port.c
@@ -875,6 +875,15 @@ mm_serial_port_open (MMSerialPort *self, GError **error)
priv = MM_SERIAL_PORT_GET_PRIVATE (self);
device = mm_port_get_device (MM_PORT (self));
+ if (priv->forced_close) {
+ g_set_error (error,
+ MM_SERIAL_ERROR,
+ MM_SERIAL_ERROR_OPEN_FAILED,
+ "Could not open serial device %s: it has been forced close",
+ device);
+ return FALSE;
+ }
+
if (priv->reopen_id) {
g_set_error (error,
MM_SERIAL_ERROR,
@@ -1293,6 +1302,17 @@ mm_serial_port_reopen (MMSerialPort *self,
g_return_val_if_fail (MM_IS_SERIAL_PORT (self), FALSE);
priv = MM_SERIAL_PORT_GET_PRIVATE (self);
+ if (priv->forced_close) {
+ GError *error;
+
+ error = g_error_new_literal (MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Serial port has been forced close.");
+ callback (self, error, user_data);
+ g_error_free (error);
+ return FALSE;
+ }
+
if (priv->reopen_id > 0) {
GError *error;