]> sigrok.org Git - libserialport.git/commitdiff
Add an example of proper error handling.
authorMartin Ling <redacted>
Mon, 20 Jan 2020 08:28:25 +0000 (08:28 +0000)
committerMartin Ling <redacted>
Thu, 23 Jan 2020 04:10:00 +0000 (04:10 +0000)
Makefile.am
examples/.gitignore
examples/handle_errors.c [new file with mode: 0644]
libserialport.h

index 426ceacd647d34b1cb8db6afaf1ebca7b071ad9c..d7e9fadb2558203efb384eacc7541cf9359d62e7 100644 (file)
@@ -66,7 +66,8 @@ EXTRA_DIST = Doxyfile \
        examples/README \
        examples/list_ports.c \
        examples/port_info.c \
-       examples/port_config.c
+       examples/port_config.c \
+       examples/handle_errors.c
 
 MAINTAINERCLEANFILES = ChangeLog
 
index 6f681be6b5c1f595d230443af0f5f2239be8b4f9..80e56cee16603465553711d156b202c361662476 100644 (file)
@@ -1,3 +1,4 @@
+handle_errors
 list_ports
 port_info
 port_config
diff --git a/examples/handle_errors.c b/examples/handle_errors.c
new file mode 100644 (file)
index 0000000..da8e8e9
--- /dev/null
@@ -0,0 +1,116 @@
+#include <libserialport.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Example of how to handle errors from libserialport.
+ *
+ * This example file is released to the public domain. */
+
+/* Pointers used in the program to resources that may need to be freed. */
+struct sp_port **port_list = NULL;
+struct sp_port_config *config = NULL;
+struct sp_port *port = NULL;
+
+/* Example of a function to clean up and exit the program with a given return code. */
+void end_program(int return_code)
+{
+       /* Free any structures we allocated. */
+       if (port_list != NULL)
+               sp_free_port_list(port_list);
+       if (config != NULL)
+               sp_free_config(config);
+       if (port != NULL)
+               sp_free_port(port);
+
+       /* Exit with the given return code. */
+       exit(return_code);
+}
+
+/* Example of a helper function for error handling. */
+int check(enum sp_return result)
+{
+       int error_code;
+       char *error_message;
+       switch (result) {
+
+               /* Handle each of the four negative error codes that can be returned.
+                *
+                * In this example, we will end the program on any error, using
+                * a different return code for each possible class of error. */
+
+               case SP_ERR_ARG:
+                       /* When SP_ERR_ARG is returned, there was a problem with one
+                        * or more of the arguments passed to the function, e.g. a null
+                        * pointer or an invalid value. This generally implies a bug in
+                        * the calling code. */
+                       printf("Error: Invalid argument.\n");
+                       end_program(1);
+
+               case SP_ERR_FAIL:
+                       /* When SP_ERR_FAIL is returned, there was an error from the OS,
+                        * which we can obtain the error code and message for. These
+                        * calls must be made in the same thread as the call that
+                        * returned SP_ERR_FAIL, and before any other system functions
+                        * are called in that thread, or they may not return the
+                        * correct results. */
+                       error_code = sp_last_error_code();
+                       error_message = sp_last_error_message();
+                       printf("Error: Failed: OS error code: %d, message: '%s'\n",
+                               error_code, error_message);
+                       /* The error message should be freed after use. */
+                       sp_free_error_message(error_message);
+                       end_program(2);
+
+               case SP_ERR_SUPP:
+                       /* When SP_ERR_SUPP is returned, the function was asked to do
+                        * something that isn't supported by the current OS or device,
+                        * or that libserialport doesn't know how to do in the current
+                        * version. */
+                       printf("Error: Not supported.\n");
+                       end_program(3);
+
+               case SP_ERR_MEM:
+                       /* When SP_ERR_MEM is returned, libserialport wasn't able to
+                        * allocate some memory it needed. Since the library doesn't
+                        * normally use any large data structures, this probably means
+                        * the system is critically low on memory and recovery will
+                        * require very careful handling. The library itself will
+                        * always try to handle any allocation failure safely.
+                        *
+                        * In this example, we'll just try to exit gracefully without
+                        * calling printf, which might need to allocate further memory. */
+                       end_program(4);
+
+               case SP_OK:
+               default:
+                       /* A return value of SP_OK, defined as zero, means that the
+                        * operation succeeded. */
+                       printf("Operation succeeded.\n");
+
+                       /* Some fuctions can also return a value greater than zero to
+                        * indicate a numeric result, such as the number of bytes read by
+                        * sp_blocking_read(). So when writing an error handling wrapper
+                        * function like this one, it's helpful to return the result so
+                        * that it can be used. */
+                       return result;
+       }
+}
+
+int main(int argc, char **argv)
+{
+       /* Call some functions that should not result in errors. */
+
+       printf("Getting list of ports.\n");
+       check(sp_list_ports(&port_list));
+
+       printf("Creating a new port configuration.\n");
+       check(sp_new_config(&config));
+
+       /* Now make a function call that will result in an error. */
+
+       printf("Trying to find a port that doesn't exist.\n");
+       check(sp_get_port_by_name("NON-EXISTENT-PORT", &port));
+
+       /* We could now clean up and exit normally if an error hadn't occured. */
+       end_program(0);
+}
index 09af4ff0672f226958b013a954d329466d520354..65f96799933a008fab903cc9be95b175668e744e 100644 (file)
@@ -68,6 +68,7 @@
  * - @ref list_ports.c - Getting a list of ports present on the system.
  * - @ref port_info.c - Getting information on a particular serial port.
  * - @ref port_config.c - Accessing configuration settings of a port.
+ * - @ref handle_errors.c - Handling errors returned from the library.
  *
  * These examples are linked with the API documentation. Each function
  * in the API reference includes links to where it is used in an example
@@ -1596,6 +1597,8 @@ SP_API enum sp_return sp_end_break(struct sp_port *port);
  *
  * Obtaining error information.
  *
+ * See @ref handle_errors.c for an example of error handling.
+ *
  * @{
  */
 
@@ -1806,6 +1809,7 @@ SP_API const char *sp_get_lib_version_string(void);
  * @example list_ports.c Getting a list of ports present on the system.
  * @example port_info.c Getting information on a particular serial port.
  * @example port_config.c Accessing configuration settings of a port.
+ * @example handle_errors.c - Handling errors returned from the library.
 */
 
 #ifdef __cplusplus