Simplify the error handling in the close function.

When the close function returns, all resources should be freed,
regardless of whether an error has occured or not. The error code is
purely informative.

However, in order to return the first error code, which is usually the
most interesting one, the current implementation is unnecessary
complicated. If an error occurs, there is no need to exit immediately.
Simply store the error code unless there is already a previous one, and
then continue.
This commit is contained in:
Jef Driesen 2015-10-12 19:51:52 +02:00
parent 18d4d5dcc0
commit f1c0249053
36 changed files with 186 additions and 112 deletions

View File

@ -210,6 +210,10 @@
RelativePath="..\src\citizen_aqualand_parser.c"
>
</File>
<File
RelativePath="..\src\common.c"
>
</File>
<File
RelativePath="..\src\context.c"
>
@ -520,6 +524,10 @@
RelativePath="..\include\libdivecomputer\citizen_aqualand.h"
>
</File>
<File
RelativePath="..\src\common-private.h"
>
</File>
<File
RelativePath="..\src\context-private.h"
>

View File

@ -17,6 +17,7 @@ libdivecomputer_la_SOURCES = \
version.c \
descriptor.c \
iterator-private.h iterator.c \
common-private.h common.c \
context-private.h context.c \
device-private.h device.c \
parser-private.h parser.c \

View File

@ -125,18 +125,18 @@ error_free:
static dc_status_t
citizen_aqualand_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
citizen_aqualand_device_t *device = (citizen_aqualand_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

37
src/common-private.h Normal file
View File

@ -0,0 +1,37 @@
/*
* libdivecomputer
*
* Copyright (C) 2015 Jef Driesen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef COMMON_PRIVATE_H
#define COMMON_PRIVATE_H
#include <libdivecomputer/common.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void
dc_status_set_error (dc_status_t *status, dc_status_t error);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* COMMON_PRIVATE_H */

34
src/common.c Normal file
View File

@ -0,0 +1,34 @@
/*
* libdivecomputer
*
* Copyright (C) 2015 Jef Driesen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include <stdlib.h>
#include <assert.h>
#include "common-private.h"
void
dc_status_set_error (dc_status_t *status, dc_status_t error)
{
assert (status != NULL);
if (*status == DC_STATUS_SUCCESS)
*status = error;
}

View File

@ -331,6 +331,7 @@ error_free:
static dc_status_t
cressi_edy_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
cressi_edy_device_t *device = (cressi_edy_device_t*) abstract;
// Send the quit command.
@ -338,14 +339,13 @@ cressi_edy_device_close (dc_device_t *abstract)
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -142,18 +142,18 @@ error_free:
static dc_status_t
cressi_leonardo_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
cressi_leonardo_device_t *device = (cressi_leonardo_device_t *) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}
static dc_status_t

View File

@ -27,6 +27,8 @@
#include <libdivecomputer/context.h>
#include <libdivecomputer/device.h>
#include "common-private.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

View File

@ -218,6 +218,7 @@ error_free:
static dc_status_t
diverite_nitekq_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
diverite_nitekq_device_t *device = (diverite_nitekq_device_t*) abstract;
// Disconnect.
@ -225,14 +226,13 @@ diverite_nitekq_device_close (dc_device_t *abstract)
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -173,18 +173,18 @@ error_free:
static dc_status_t
divesystem_idive_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
divesystem_idive_device_t *device = (divesystem_idive_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -271,27 +271,26 @@ error_free:
static dc_status_t
hw_frog_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
hw_frog_device_t *device = (hw_frog_device_t*) abstract;
dc_status_t rc = DC_STATUS_SUCCESS;
// Send the exit command.
dc_status_t status = hw_frog_transfer (device, NULL, EXIT, NULL, 0, NULL, 0);
if (status != DC_STATUS_SUCCESS) {
rc = hw_frog_transfer (device, NULL, EXIT, NULL, 0, NULL, 0);
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
serial_close (device->port);
free (device);
return status;
dc_status_set_error(&status, rc);
}
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -187,18 +187,18 @@ error_free:
static dc_status_t
hw_ostc_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
hw_ostc_device_t *device = (hw_ostc_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -430,6 +430,7 @@ hw_ostc3_device_init (hw_ostc3_device_t *device, hw_ostc3_state_t state)
static dc_status_t
hw_ostc3_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
hw_ostc3_device_t *device = (hw_ostc3_device_t*) abstract;
dc_status_t rc = DC_STATUS_SUCCESS;
@ -438,22 +439,19 @@ hw_ostc3_device_close (dc_device_t *abstract)
rc = hw_ostc3_transfer (device, NULL, EXIT, NULL, 0, NULL, 0);
if (rc != DC_STATUS_SUCCESS) {
ERROR (abstract->context, "Failed to send the command.");
serial_close (device->port);
free (device);
return rc;
dc_status_set_error(&status, rc);
}
}
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -133,6 +133,8 @@ error_free:
int
irda_socket_close (irda_t *device)
{
int errcode = 0;
if (device == NULL)
return -1;
@ -146,26 +148,21 @@ irda_socket_close (irda_t *device)
if (close (device->fd) != 0) {
#endif
SYSERROR (device->context, ERRNO);
#ifdef _WIN32
WSACleanup ();
#endif
free (device);
return -1;
errcode = -1;
}
#ifdef _WIN32
// Terminate the winsock dll.
if (WSACleanup () != 0) {
SYSERROR (device->context, ERRNO);
free (device);
return -1;
errcode = -1;
}
#endif
// Free memory.
free (device);
return 0;
return errcode;
}

View File

@ -173,18 +173,18 @@ error_free:
static dc_status_t
mares_darwin_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
mares_darwin_device_t *device = (mares_darwin_device_t *) abstract;
// Close the device.
if (serial_close (device->base.port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -324,18 +324,18 @@ error_free:
static dc_status_t
mares_iconhd_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
mares_iconhd_device_t *device = (mares_iconhd_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -159,18 +159,18 @@ error_free:
static dc_status_t
mares_nemo_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
mares_nemo_device_t *device = (mares_nemo_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -181,18 +181,18 @@ error_free:
static dc_status_t
mares_puck_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
mares_puck_device_t *device = (mares_puck_device_t*) abstract;
// Close the device.
if (serial_close (device->base.port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -651,6 +651,7 @@ error_free:
static dc_status_t
oceanic_atom2_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
oceanic_atom2_device_t *device = (oceanic_atom2_device_t*) abstract;
// Send the quit command.
@ -658,14 +659,13 @@ oceanic_atom2_device_close (dc_device_t *abstract)
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -314,6 +314,7 @@ error_free:
static dc_status_t
oceanic_veo250_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
oceanic_veo250_device_t *device = (oceanic_veo250_device_t*) abstract;
// Switch the device back to surface mode.
@ -321,14 +322,13 @@ oceanic_veo250_device_close (dc_device_t *abstract)
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -357,6 +357,7 @@ error_free:
static dc_status_t
oceanic_vtpro_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t*) abstract;
// Switch the device back to surface mode.
@ -364,14 +365,13 @@ oceanic_vtpro_device_close (dc_device_t *abstract)
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -154,6 +154,7 @@ error_free:
static dc_status_t
reefnet_sensus_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
reefnet_sensus_device_t *device = (reefnet_sensus_device_t*) abstract;
// Safely close the connection if the last handshake was
@ -163,14 +164,13 @@ reefnet_sensus_device_close (dc_device_t *abstract)
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -132,18 +132,18 @@ error_free:
static dc_status_t
reefnet_sensuspro_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
reefnet_sensuspro_device_t *device = (reefnet_sensuspro_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -141,18 +141,18 @@ error_free:
static dc_status_t
reefnet_sensusultra_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
reefnet_sensusultra_device_t *device = (reefnet_sensusultra_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -195,15 +195,15 @@ error_free:
int
serial_close (serial_t *device)
{
int errcode = 0;
if (device == NULL)
return 0;
// Restore the initial terminal attributes.
if (tcsetattr (device->fd, TCSANOW, &device->tty) != 0) {
SYSERROR (device->context, errno);
close (device->fd);
free (device);
return -1;
errcode = -1;
}
#ifndef ENABLE_PTY
@ -214,14 +214,13 @@ serial_close (serial_t *device)
// Close the device.
if (close (device->fd) != 0) {
SYSERROR (device->context, errno);
free (device);
return -1;
errcode = -1;
}
// Free memory.
free (device);
return 0;
return errcode;
}
//

View File

@ -181,6 +181,8 @@ error_free:
int
serial_close (serial_t *device)
{
int errcode = 0;
if (device == NULL)
return 0;
@ -188,22 +190,19 @@ serial_close (serial_t *device)
if (!SetCommState (device->hFile, &device->dcb) ||
!SetCommTimeouts (device->hFile, &device->timeouts)) {
SYSERROR (device->context, GetLastError ());
CloseHandle (device->hFile);
free (device);
return -1;
errcode = -1;
}
// Close the device.
if (!CloseHandle (device->hFile)) {
SYSERROR (device->context, GetLastError ());
free (device);
return -1;
errcode = -1;
}
// Free memory.
free (device);
return 0;
return errcode;
}
//

View File

@ -215,18 +215,18 @@ error_free:
static dc_status_t
suunto_d9_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
suunto_d9_device_t *device = (suunto_d9_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -135,18 +135,18 @@ error_free:
static dc_status_t
suunto_eon_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
suunto_eon_device_t *device = (suunto_eon_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -129,18 +129,18 @@ error_free:
static dc_status_t
suunto_solution_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
suunto_solution_device_t *device = (suunto_solution_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -161,18 +161,18 @@ error_free:
static dc_status_t
suunto_vyper_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
suunto_vyper_device_t *device = (suunto_vyper_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -167,18 +167,18 @@ error_free:
static dc_status_t
suunto_vyper2_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
suunto_vyper2_device_t *device = (suunto_vyper2_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -142,18 +142,18 @@ error_free:
static dc_status_t
uwatec_aladin_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
uwatec_aladin_device_t *device = (uwatec_aladin_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -141,18 +141,18 @@ error_free:
static dc_status_t
uwatec_memomouse_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
uwatec_memomouse_device_t *device = (uwatec_memomouse_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -252,18 +252,18 @@ error_free:
static dc_status_t
uwatec_meridian_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
uwatec_meridian_device_t *device = (uwatec_meridian_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -216,18 +216,18 @@ error_free:
static dc_status_t
uwatec_smart_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
uwatec_smart_device_t *device = (uwatec_smart_device_t*) abstract;
// Close the device.
if (irda_socket_close (device->socket) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}

View File

@ -201,18 +201,18 @@ error_free:
static dc_status_t
zeagle_n2ition3_device_close (dc_device_t *abstract)
{
dc_status_t status = DC_STATUS_SUCCESS;
zeagle_n2ition3_device_t *device = (zeagle_n2ition3_device_t*) abstract;
// Close the device.
if (serial_close (device->port) == -1) {
free (device);
return DC_STATUS_IO;
dc_status_set_error(&status, DC_STATUS_IO);
}
// Free memory.
free (device);
return DC_STATUS_SUCCESS;
return status;
}