Added guac_error_message. Added error messages to all functions.

This commit is contained in:
Michael Jumper 2011-11-27 15:57:43 -08:00
parent 2d02a0f3bd
commit f935075aec
5 changed files with 83 additions and 6 deletions

View File

@ -116,4 +116,17 @@ const char* guac_status_string(guac_status status);
guac_status* __guac_error(); guac_status* __guac_error();
/**
* Returns a message describing the error which occurred during the last
* function call. If an error occurred, but no message is associated with it,
* NULL is returned. This value is undefined if no error occurred.
*
* The storage of this value is thread-local. Assignment of a message to
* guac_error_message in one thread will not affect its value in another
* thread.
*/
#define guac_error_message (*__guac_error_message())
const char** __guac_error_message();
#endif #endif

View File

@ -135,6 +135,7 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol) {
client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY); client_plugin_handle = dlopen(protocol_lib, RTLD_LAZY);
if (!client_plugin_handle) { if (!client_plugin_handle) {
guac_error = GUAC_STATUS_BAD_ARGUMENT; guac_error = GUAC_STATUS_BAD_ARGUMENT;
guac_error_message = "Client plugin not found";
return NULL; return NULL;
} }
@ -146,6 +147,7 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol) {
/* Fail if cannot find guac_client_init */ /* Fail if cannot find guac_client_init */
if (dlerror() != NULL) { if (dlerror() != NULL) {
guac_error = GUAC_STATUS_BAD_ARGUMENT; guac_error = GUAC_STATUS_BAD_ARGUMENT;
guac_error_message = dlerror();
return NULL; return NULL;
} }
@ -155,6 +157,7 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol) {
/* Fail if cannot find GUAC_CLIENT_ARGS */ /* Fail if cannot find GUAC_CLIENT_ARGS */
if (dlerror() != NULL) { if (dlerror() != NULL) {
guac_error = GUAC_STATUS_BAD_ARGUMENT; guac_error = GUAC_STATUS_BAD_ARGUMENT;
guac_error_message = dlerror();
return NULL; return NULL;
} }
@ -162,6 +165,7 @@ guac_client_plugin* guac_client_plugin_open(const char* protocol) {
plugin = malloc(sizeof(guac_client_plugin)); plugin = malloc(sizeof(guac_client_plugin));
if (plugin == NULL) { if (plugin == NULL) {
guac_error = GUAC_STATUS_NO_MEMORY; guac_error = GUAC_STATUS_NO_MEMORY;
guac_error_message = "Could not allocate memory for client plugin";
return NULL; return NULL;
} }
@ -178,6 +182,7 @@ int guac_client_plugin_close(guac_client_plugin* plugin) {
/* Unload client plugin */ /* Unload client plugin */
if (dlclose(plugin->__client_plugin_handle)) { if (dlclose(plugin->__client_plugin_handle)) {
guac_error = GUAC_STATUS_BAD_STATE; guac_error = GUAC_STATUS_BAD_STATE;
guac_error_message = dlerror();
return -1; return -1;
} }
@ -192,6 +197,7 @@ guac_client* guac_client_plugin_get_client(guac_client_plugin* plugin,
guac_client* client = malloc(sizeof(guac_client)); guac_client* client = malloc(sizeof(guac_client));
if (client == NULL) { if (client == NULL) {
guac_error = GUAC_STATUS_NO_MEMORY; guac_error = GUAC_STATUS_NO_MEMORY;
guac_error_message = "Could not allocate memory for client";
return NULL; return NULL;
} }

View File

@ -107,17 +107,27 @@ const char* guac_status_string(guac_status status) {
static pthread_key_t __guac_error_key; static pthread_key_t __guac_error_key;
static pthread_once_t __guac_error_key_init = PTHREAD_ONCE_INIT; static pthread_once_t __guac_error_key_init = PTHREAD_ONCE_INIT;
static void __guac_free_error(void* status) { static pthread_key_t __guac_error_message_key;
static pthread_once_t __guac_error_message_key_init = PTHREAD_ONCE_INIT;
static void __guac_free_pointer(void* pointer) {
/* Free memory allocated to status variable */ /* Free memory allocated to status variable */
free(status); free(pointer);
} }
static void __guac_alloc_error_key() { static void __guac_alloc_error_key() {
/* Create key, destroy any allocated variable on thread exit */ /* Create key, destroy any allocated variable on thread exit */
pthread_key_create(&__guac_error_key, __guac_free_error); pthread_key_create(&__guac_error_key, __guac_free_pointer);
}
static void __guac_alloc_error_message_key() {
/* Create key, destroy any allocated variable on thread exit */
pthread_key_create(&__guac_error_message_key, __guac_free_pointer);
} }
@ -142,15 +152,44 @@ guac_status* __guac_error() {
} }
const char** __guac_error_message() {
/* Pointer for thread-local data */
const char** message;
/* Init error message key, if not already initialized */
pthread_once(
&__guac_error_message_key_init,
__guac_alloc_error_message_key
);
/* Retrieve thread-local message variable */
message = (const char**) pthread_getspecific(__guac_error_message_key);
/* Allocate thread-local message variable if not already allocated */
if (message == NULL) {
message = malloc(sizeof(const char*));
pthread_setspecific(__guac_error_message_key, message);
}
return message;
}
#else #else
/* Default (not-threadsafe) implementation */ /* Default (not-threadsafe) implementation */
static guac_status __guac_error_unsafe_storage; static guac_status __guac_error_unsafe_storage;
static const char** __guac_error_message_unsafe_storage;
guac_status* __guac_error() { guac_status* __guac_error() {
return &__guac_error_unsafe_storage; return &__guac_error_unsafe_storage;
} }
const char** __guac_error_message() {
return &__guac_error_message_unsafe_storage;
}
/* Warn about threadsafety */ /* Warn about threadsafety */
#warn No threadsafe implementation of __guac_error exists for your platform, so a default non-threadsafe implementation has been used instead. This may lead to incorrect status codes being reported for failures. Please consider adding support for your platform, or filing a bug report with the Guacamole project. #warn No threadsafe implementation of __guac_error exists for your platform, so a default non-threadsafe implementation has been used instead. This may lead to incorrect status codes being reported for failures. Please consider adding support for your platform, or filing a bug report with the Guacamole project.

View File

@ -414,6 +414,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t
parsed_instruction = malloc(sizeof(guac_instruction)); parsed_instruction = malloc(sizeof(guac_instruction));
if (parsed_instruction == NULL) { if (parsed_instruction == NULL) {
guac_error = GUAC_STATUS_NO_MEMORY; guac_error = GUAC_STATUS_NO_MEMORY;
guac_error_message = "Could not allocate memory for parsed instruction";
return NULL; return NULL;
} }
@ -424,6 +425,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t
/* Fail if memory could not be alloc'd for argv */ /* Fail if memory could not be alloc'd for argv */
if (parsed_instruction->argv == NULL) { if (parsed_instruction->argv == NULL) {
guac_error = GUAC_STATUS_NO_MEMORY; guac_error = GUAC_STATUS_NO_MEMORY;
guac_error_message = "Could not allocate memory for arguments of parsed instruction";
free(parsed_instruction); free(parsed_instruction);
return NULL; return NULL;
} }
@ -434,6 +436,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t
/* Fail if memory could not be alloc'd for opcode */ /* Fail if memory could not be alloc'd for opcode */
if (parsed_instruction->opcode == NULL) { if (parsed_instruction->opcode == NULL) {
guac_error = GUAC_STATUS_NO_MEMORY; guac_error = GUAC_STATUS_NO_MEMORY;
guac_error_message = "Could not allocate memory for opcode of parsed instruction";
free(parsed_instruction->argv); free(parsed_instruction->argv);
free(parsed_instruction); free(parsed_instruction);
return NULL; return NULL;
@ -447,6 +450,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t
/* Free memory and fail if out of mem */ /* Free memory and fail if out of mem */
if (parsed_instruction->argv[j] == NULL) { if (parsed_instruction->argv[j] == NULL) {
guac_error = GUAC_STATUS_NO_MEMORY; guac_error = GUAC_STATUS_NO_MEMORY;
guac_error_message = "Could not allocate memory for single argument of parsed instruction";
/* Free all alloc'd argv values */ /* Free all alloc'd argv values */
while (--j >= 0) while (--j >= 0)
@ -474,6 +478,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t
/* Error if expected comma is not present */ /* Error if expected comma is not present */
else if (terminator != ',') { else if (terminator != ',') {
guac_error = GUAC_STATUS_BAD_ARGUMENT; guac_error = GUAC_STATUS_BAD_ARGUMENT;
guac_error_message = "Element terminator of instructioni was not ';' nor ','";
return NULL; return NULL;
} }
@ -488,6 +493,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t
/* Error if length is non-numeric or does not end in a period */ /* Error if length is non-numeric or does not end in a period */
else { else {
guac_error = GUAC_STATUS_BAD_ARGUMENT; guac_error = GUAC_STATUS_BAD_ARGUMENT;
guac_error_message = "Non-numeric character in element length";
return NULL; return NULL;
} }
@ -508,6 +514,7 @@ guac_instruction* guac_protocol_read_instruction(guac_socket* socket, int usec_t
/* EOF */ /* EOF */
if (retval == 0) { if (retval == 0) {
guac_error = GUAC_STATUS_NO_INPUT; guac_error = GUAC_STATUS_NO_INPUT;
guac_error_message = "End of stream reached while reading instruction";
return NULL; return NULL;
} }
@ -532,6 +539,7 @@ guac_instruction* guac_protocol_expect_instruction(guac_socket* socket, int usec
/* Validate instruction */ /* Validate instruction */
if (strcmp(instruction->opcode, opcode) != 0) { if (strcmp(instruction->opcode, opcode) != 0) {
guac_error = GUAC_STATUS_BAD_STATE; guac_error = GUAC_STATUS_BAD_STATE;
guac_error_message = "Instruction read did not have expected opcode";
guac_instruction_free(instruction); guac_instruction_free(instruction);
return NULL; return NULL;
} }

View File

@ -69,6 +69,7 @@ guac_socket* guac_socket_open(int fd) {
/* If no memory available, return with error */ /* If no memory available, return with error */
if (socket == NULL) { if (socket == NULL) {
guac_error = GUAC_STATUS_NO_MEMORY; guac_error = GUAC_STATUS_NO_MEMORY;
guac_error_message = "Could not allocate memory for socket";
return NULL; return NULL;
} }
@ -83,6 +84,7 @@ guac_socket* guac_socket_open(int fd) {
/* If no memory available, return with error */ /* If no memory available, return with error */
if (socket->__instructionbuf == NULL) { if (socket->__instructionbuf == NULL) {
guac_error = GUAC_STATUS_NO_MEMORY; guac_error = GUAC_STATUS_NO_MEMORY;
guac_error_message = "Could not allocate memory for instruction buffer";
free(socket); free(socket);
return NULL; return NULL;
} }
@ -116,8 +118,10 @@ ssize_t __guac_socket_write(guac_socket* socket, const char* buf, int count) {
#endif #endif
/* Record errors in guac_error */ /* Record errors in guac_error */
if (retval < 0) if (retval < 0) {
guac_error = GUAC_STATUS_SEE_ERRNO; guac_error = GUAC_STATUS_SEE_ERRNO;
guac_error_message = "Error writing data to socket";
}
return retval; return retval;
} }
@ -299,8 +303,15 @@ int guac_socket_select(guac_socket* socket, int usec_timeout) {
} }
/* Properly set guac_error */ /* Properly set guac_error */
if (retval < 0) guac_error = GUAC_STATUS_SEE_ERRNO; if (retval < 0) {
if (retval == 0) guac_error = GUAC_STATUS_INPUT_TIMEOUT; guac_error = GUAC_STATUS_SEE_ERRNO;
guac_error_message = "Error while waiting for data on socket";
}
if (retval == 0) {
guac_error = GUAC_STATUS_INPUT_TIMEOUT;
guac_error_message = "Timeout while waiting for data on socket";
}
return retval; return retval;