Simplify logging and remove unwanted functions from abstraction layer

Signed-off-by: Jeroen Koekkoek <jeroen@koekkoek.nl>
This commit is contained in:
Jeroen Koekkoek 2018-11-26 19:10:09 +01:00
parent ac020f62f7
commit 1cf03332ca
97 changed files with 2819 additions and 5361 deletions

View file

@ -11,7 +11,6 @@
#
string(TOLOWER ${CMAKE_SYSTEM_NAME} platform)
# For posix platforms include the files in the posix/ directory.
set (posix_platforms darwin linux sunos)
IF(${platform} IN_LIST posix_platforms)
set(platform posix)
@ -21,7 +20,8 @@ ENDIF()
PREPEND(srcs_platform ${platform} os_platform_errno.c os_platform_heap.c os_platform_init.c os_platform_process.c os_platform_ifaddrs.c os_platform_socket.c os_platform_stdlib.c os_platform_sync.c os_platform_thread.c os_platform_time.c)
include (GenerateExportHeader)
PREPEND(srcs_os "${CMAKE_CURRENT_SOURCE_DIR}/src" os_atomics.c os_init.c os_report.c os_ifaddrs.c os_socket.c os_thread.c os_time.c os_errno.c os_iter.c ${srcs_platform})
PREPEND(srcs_os "${CMAKE_CURRENT_SOURCE_DIR}/src" os_atomics.c os_init.c os_log.c os_ifaddrs.c os_socket.c os_thread.c os_time.c os_errno.c os_iter.c ${srcs_platform})
add_library(OSAPI ${srcs_os})
configure_file(

View file

@ -49,12 +49,11 @@
#include "os_socket.h"
#include "os_heap.h"
#include "os_stdlib.h"
#include "os_report.h"
#include "os_init.h"
#include "os_process.h"
#include "os_errno.h"
#include "os_iter.h"
#include "os_log.h"
#define OSPL_VERSION_STR "aap"
#define OSPL_HOST_STR "noot"

234
src/os/include/os/os_log.h Normal file
View file

@ -0,0 +1,234 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
/** @file
*
* @brief DDS C Logging API
*
* This header file defines the public API for logging and controlling logging
* in the DDS C language binding.
*/
#ifndef DDS_LOG_H
#define DDS_LOG_H
#include "os/os_defs.h"
#if defined (__cplusplus)
extern "C" {
#endif
/** @defgroup log_categories Convenience log category definitions.
*
* These defines expand into numeric values that can be ORed together to
* specify messages of which categories must be passed to the respective sinks.
*
* Every category other than DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING and
* DDS_LC_INFO automatically falls into the trace category.
*
* @{
*/
/** Fatal error condition. Immediate abort on sink return. */
#define DDS_LC_FATAL (1u)
/** Error condition. */
#define DDS_LC_ERROR (2u)
/** Warning condition. */
#define DDS_LC_WARNING (4u)
/** Informational message. */
#define DDS_LC_INFO (8u)
/** Debug/trace messages related to configuration settings. */
#define DDS_LC_CONFIG (16u)
/** Debug/trace messages related to node discovery. */
#define DDS_LC_DISCOVERY (32u)
/** Currently unused. */
#define DDS_LC_DATA (64u)
/** Debug/trace messages for which no specialized category exists (yet). */
#define DDS_LC_TRACE (128u)
/** Debug/trace messages related to receive administration. */
#define DDS_LC_RADMIN (256u)
/** Debug/trace messages related to timing. */
#define DDS_LC_TIMING (512u)
/** Debug/trace messages related to send administration. */
#define DDS_LC_TRAFFIC (1024u)
/** Currently unused. */
#define DDS_LC_TOPIC (2048u)
/** Debug/trace messages related to TCP communication. */
#define DDS_LC_TCP (4096u)
/** Debug/trace messages related to parameter list processing. */
#define DDS_LC_PLIST (8192u)
/** Debug/trace messages related to the writer history cache. */
#define DDS_LC_WHC (16384u)
/** Debug/trace messages related to throttling. */
#define DDS_LC_THROTTLE (32768u)
/** All common trace categories. */
#define DDS_LC_ALL \
(DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_INFO | \
DDS_LC_CONFIG | DDS_LC_DISCOVERY | DDS_LC_DATA | DDS_LC_TRACE | \
DDS_LC_TIMING | DDS_LC_TRAFFIC | DDS_LC_TCP | DDS_LC_THROTTLE)
/** @}*/
#define DDS_LOG_MASK \
(DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_INFO)
#define DDS_TRACE_MASK \
(~DDS_LOG_MASK)
/** Structure with log message and meta data passed to callbacks. */
typedef struct {
/** Log category the message falls into. */
uint32_t priority;
/** Filename where message was generated. */
const char *file;
/** Line number in file where message was generated. */
uint32_t line;
/** Name of function message where message was generated. */
const char *function;
/** Log message. */
const char *message;
/** Size of log message. */
size_t size;
} dds_log_data_t;
/** Function signature that log and trace callbacks must adhere too. */
typedef void(*dds_log_write_fn_t)(void *, const dds_log_data_t *);
extern uint32_t *const dds_log_mask;
/**
* @brief Get currently enabled log and trace categories.
*
* @returns A uint32_t with enabled categories set.
*/
inline uint32_t
dds_get_log_mask(void)
{
return *dds_log_mask;
}
/**
* @brief Set enabled log and trace categories.
*
* @param[in] cats Log and trace categories to enable.
*/
OSAPI_EXPORT void
dds_set_log_mask(
_In_ uint32_t cats);
/**
* @private
*/
OSAPI_EXPORT void
dds_set_log_file(
_In_ FILE *file);
/**
* @private
*/
OSAPI_EXPORT void
dds_set_trace_file(
_In_ FILE *file);
/**
* @brief Register callback to receive log messages
*
* Callbacks registered to handle log messages will receive messages of type
* info, warning, error and fatal. Messages that fall into the trace category
* will never be delivered to the callback.
*
* This operation is synchronous and only returns once the operation is
* registered with all threads. Meaning that neither callback or userdata will
* be referenced by the DDS stack on return.
*
* @param[in] callback Function pointer matching dds_log_write_fn signature
* or a null pointer to restore the default sink.
* @param[in] userdata User specified data passed along with each invocation
* of callback.
*/
OSAPI_EXPORT void
dds_set_log_sink(
_In_opt_ dds_log_write_fn_t callback,
_In_opt_ void *userdata);
/**
* @brief Register callback to receive trace messages
*
* Callbacks registered to handle trace messages will receive messages of type
* info, warning, error and fatal as well as all message types that fall into
* the trace category depending on the log mask.
*
* This operation is synchronous and only returns once the operation is
* registered with all threads. Meaning that neither callback or
* userdata will be referenced by the DDS stack on return.
*
* @param[in] callback Function pointer matching dds_log_write_fn_t signature
* or a null pointer to restore the default sink.
* @param[in] userdata User specified data passed along with each invocation
* of callback.
*/
OSAPI_EXPORT void
dds_set_trace_sink(
_In_opt_ dds_log_write_fn_t callback,
_In_opt_ void *userdata);
/**
* @brief Write a log or trace message.
*
* Write a log or trace message to one (or both) of the currently active sinks.
*
* Direct use of #dds_log is discouraged. Use #DDS_INFO, #DDS_WARNING,
* #DDS_ERROR, #DDS_FATAL or #DDS_LOG instead.
*/
OSAPI_EXPORT int
dds_log(
_In_ uint32_t prio,
_In_z_ const char *file,
_In_ uint32_t line,
_In_z_ const char *func,
_In_z_ _Printf_format_string_ const char *fmt,
...) __attribute_format__((printf,5,6));
/**
* @brief Write a log message.
*
* Write a log or trace message to the currently active log and/or trace sinks
* if the log category is enabled. Whether or not the category is enabled is
* checked before any dds_log-related activities to save a couple of % CPU.
*
* Only messages that fall into one of the log categories are passed onto
* dds_log. While messages that fall into a trace category could have been
* passed just as easily, they are rejected so that tracing is kept entirely
* separate from logging, if only cosmetic.
*/
#define DDS_LOG(cat, ...) \
((dds_get_log_mask() & (cat)) ? \
dds_log(cat, __FILE__, __LINE__, OS_FUNCTION, __VA_ARGS__) : 0)
/** Write a log message of type #DDS_LC_INFO. */
#define DDS_INFO(...) \
DDS_LOG(DDS_LC_INFO, __VA_ARGS__)
/** Write a log message of type #DDS_LC_WARNING. */
#define DDS_WARNING(...) \
DDS_LOG(DDS_LC_WARNING, __VA_ARGS__)
/** Write a log message of type #DDS_LC_ERROR. */
#define DDS_ERROR(...) \
DDS_LOG(DDS_LC_ERROR, __VA_ARGS__)
/** Write a log message of type #DDS_LC_ERROR and abort. */
#define DDS_FATAL(...) \
dds_log(DDS_LC_FATAL, __FILE__, __LINE__, OS_FUNCTION, __VA_ARGS__)
/** Write a #DDS_LC_TRACE message. */
#define DDS_TRACE(...) \
DDS_LOG(DDS_LC_TRACE, __VA_ARGS__)
#if defined (__cplusplus)
}
#endif
#endif /* DDS_LOG_H */

View file

@ -1,137 +0,0 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef OS_REPORT_H
#define OS_REPORT_H
#include <stdarg.h>
#if defined (__cplusplus)
extern "C" {
#endif
/* !!!!!!!!NOTE From here no more includes are allowed!!!!!!! */
/* Subcomponents might need to alter the report before actually handing it over
* to os_report. Since os_report truncates messages, those components can get
* away with fixed size buffers as well, but the maximum size must known at
* that point.
*/
#define OS_REPORT_BUFLEN 1024
/*
Note - in the below the check of reportType against os_reportVerbosity is also present
in os_report. By duplicating it we avoid putting the call onto the stack and evaluating
args if not necessary.
*/
#define OS_REPORT(type,context,code,message,...) \
(((type) >= os_reportVerbosity) ? os_report((type),(context),__FILE__,__LINE__,(code),(message),##__VA_ARGS__) : (void)0)
#define OS_DEBUG(context,code,message,...) OS_REPORT(OS_REPORT_DEBUG,(context),(code),(message),##__VA_ARGS__)
#define OS_INFO(context,code,message,...) OS_REPORT(OS_REPORT_INFO,(context),(code),(message),##__VA_ARGS__)
#define OS_WARNING(context,code,message,...) OS_REPORT(OS_REPORT_WARNING,(context),(code),(message),##__VA_ARGS__)
#define OS_ERROR(context,code,message,...) OS_REPORT(OS_REPORT_ERROR,(context),(code),(message),##__VA_ARGS__)
#define OS_CRITICAL(context,code,message,...) OS_REPORT(OS_REPORT_CRITICAL,(context),(code),(message),##__VA_ARGS__)
#define OS_FATAL(context,code,message,...) OS_REPORT(OS_REPORT_FATAL,(context),(code),(message),##__VA_ARGS__)
#define OS_REPORT_STACK() \
os_report_stack()
#define OS_REPORT_FLUSH(condition) \
os_report_flush((condition), OS_FUNCTION, __FILE__, __LINE__)
/**
* These types are an ordered series of incremental 'importance' (to the user)
* levels.
* @see os_reportVerbosity
*/
typedef enum os_reportType {
OS_REPORT_DEBUG,
OS_REPORT_INFO,
OS_REPORT_WARNING,
OS_REPORT_ERROR,
OS_REPORT_FATAL,
OS_REPORT_CRITICAL,
OS_REPORT_NONE
} os_reportType;
OSAPI_EXPORT extern os_reportType os_reportVerbosity;
OSAPI_EXPORT void
os_reportInit(_In_ bool forceReInit);
OSAPI_EXPORT void
os_reportExit(void);
/** \brief Report message
*
* Consider this function private. It should be invoked by reporting functions
* specified in the language bindings only.
*
* @param type type of report
* @param context context in which report was generated, often function name
* from which function was invoked
* @param path path of file from which function was invoked
* @param line line of file from which function was invoked
* @param code error code associated with the report
* @param format message to log
* @param ... Parameter to log
*/
OSAPI_EXPORT void
os_report(
_In_ os_reportType type,
_In_z_ const char *context,
_In_z_ const char *path,
_In_ int32_t line,
_In_ int32_t code,
_In_z_ _Printf_format_string_ const char *format,
...) __attribute_format__((printf,6,7));
/*****************************************
* Report stack related functions
*****************************************/
/**
* The os_report_stack operation enables a report stack for the current thread.
* The stack will be disabled again by the os_report_flush operation.
*/
OSAPI_EXPORT void
os_report_stack(
void);
/**
* The os_report_stack_free operation frees all memory allocated by the current
* thread for the report stack.
*/
OSAPI_EXPORT void
os_report_stack_free(
void);
/**
* The os_report_flush operation removes the report message from the stack,
* and if valid is TRUE also writes them into the report device.
* This operation additionally disables the stack.
*/
OSAPI_EXPORT void
os_report_flush(
_In_ bool valid,
_In_z_ const char *context,
_In_z_ const char *file,
_In_ int line);
#if defined (__cplusplus)
}
#endif
#endif /* OS_REPORT_H */

View file

@ -82,127 +82,6 @@ extern "C" {
os_putenv(
char *variable_definition);
/** \brief Get file seperator
*
* Possible Results:
* - "<file-seperator-character>"
*/
OSAPI_EXPORT const char *
os_fileSep(void);
/** \brief Get path seperator
*
* Possible Results:
* - "<file-seperator-character>"
*/
OSAPI_EXPORT const char *
os_pathSep(void);
#define OS_PATHSEPCHAR OS_OS_PATHSEPCHAR
#define OS_EXESUFFIX OS_OS_EXESUFFIX
#define OS_BATSUFFIX OS_OS_BATSUFFIX
#define OS_LIB_LOAD_PATH_VAR OS_OS_LIB_LOAD_PATH_VAR
/** \brief Check user's permissions for a file
*
* Precondition:
* - permission is a mask of:
* OS_ROK check for read access
* OS_WOK check for write access
* OS_XOK check for execution access
* OS_FOK check for existence of the file
*
* Possible results:
* - return os_resultSuccess if
* requested file access is granted
* - return os_resultFail if
* requested file access is not granted
*/
OSAPI_EXPORT os_result
os_access(
const char *file_path,
int32_t permission);
/** \brief Locate an executable file in the path
*
* Precondition:
* - permission is a mask of:
* OS_ROK check for read access
* OS_WOK check for write access
* OS_XOK check for execution access
* OS_FOK check for existence of the file
*
* Possible results:
* - return an os_malloc-ed string if a file with
* the given permission mask was found in
* PATH. The return value contains the full
* path name of the file found.
* If the name of the file contains an
* absolute or relative path, then no
* search is done in the PATH.
* - return NULL if no file was found in PATH
*/
OSAPI_EXPORT char *
os_locate(
const char *name,
int32_t permission);
/** \brief mkdir wrapper
*
* because operating systems has different
* interfaces to mkdir a wrapper is made
*
* Precondition:
* None
*
* Possible results:
* - return 0 if
* requested dir is created
* - return -1 if
* requested dir could not be created
*/
OSAPI_EXPORT int32_t
os_mkdir(
const char *path,
os_mode_t mode);
/** \brief Create a path including parent dirs
*
* Alternative to os_mkdir that creates all path elements instead
* of only the top-level directory
*
* Preconditions:
* None
*
* Possible results:
* - return os_resultSuccess if
* requested path is created
* - return os_resultFail if
* requested path could not be created
*
* When path creation fails an appropriate error message is reported
*/
OSAPI_EXPORT os_result
os_mkpath(
const char *path,
os_mode_t mode);
/** \brief dirname wrapper
*
* because not all operating systems have
* interfaces to dirname a wrapper is made
*
* Precondition:
* None
*
* Possible results:
* - return '.' if
* path is a null pointer
* - return char *
* to a string that is the parent directory of path
*/
OSAPI_EXPORT char * os_dirname_r(char *path);
/** \brief rindex wrapper
*
* because not all operating systems have
@ -576,91 +455,6 @@ extern "C" {
OSAPI_EXPORT char *
os_strtok_r(char *str, const char *delim, char **saveptr);
struct os_stat {
/* The mode_t macro's (like OS_ISDIR) are defined in the platform specific header files! */
/* NEVER name these fields identical to the POSIX standard! Since e.g. the Linux implementation
has defined it as follows:
struct stat {
...
struct timespec st_mtim;
#define st_mtime st_mtim.tvsec
...
};
This results in the fact that our definition is also changed, causing compilation errors!
*/
os_mode_t stat_mode;
size_t stat_size;
os_time stat_mtime;
};
OSAPI_EXPORT os_result
os_stat(
const char *path,
struct os_stat *buf);
/** \brief Removes the file or directory given by name.
*
* This function is equivalent to POSIX remove(3)
*
*/
OSAPI_EXPORT os_result os_remove (const char *name);
/** \brief Renames a file or directory
*
* This function is equivalent to POSIX rename(3)
*
*/
OSAPI_EXPORT os_result os_rename (const char *oldpath, const char *newpath);
/** \brief Transforms the given filepath into a platform specific filepath.
*
* This translation function will replace any platform file seperator into
* the fileseperator of the current platform.
*
* Precondition:
* none
*
* Possible results:
* - returns normalized filepath conform current platform
* - return NULL if out of memory.
*/
_Ret_z_
_Must_inspect_result_
OSAPI_EXPORT char *
os_fileNormalize(
_In_z_ const char *filepath);
/**
* \brief Flushes the internal buffers associated with the file handle to disk
*
* Precondition:
* The file should be open.
*
* Possible results:
* - os_resultSuccess if function succeeded
* - os_resultFail if function failed
*/
OSAPI_EXPORT os_result
os_fsync(
FILE *fHandle);
/**
* \brief returns the location of the temporary files used by OpenSplice.
* This may be the key file describing the shared memory or the shared
* file itself depending on the operating system
*
* Precondition:
* none
*
* Possible results:
* - char * of the absolute path of the temporary location. This will return
* always return a valid value, using a default if necessary
*/
OSAPI_EXPORT _Ret_opt_z_ const char *
os_getTempDir(void);
/**
* \brief writes up to count bytes from the buffer pointed buf to the file referred to by the file descriptor fd.
*
@ -678,42 +472,6 @@ extern "C" {
_In_reads_bytes_(count) void const* buf,
_In_ size_t count);
/**
* \brief the os_flockfile() function waits for *filehandle to be
* no longer locked by a different thread, then makes the current
* thread owner of *filehandle, and increments the lockcount.
* (not effective on VxWorks DKM platform)
*
* Precondition:
* none
*
* Possible results:
* - No error information is returned.
* The thread will block until the lock is acquired.
* An explicit call to os_funlockfile has to be used to release the lock.
*
*/
OSAPI_EXPORT void os_flockfile(
FILE *file);
/**
* \brief the os_funlockfile function decrements the lock count and releases
* the internal locking object of the *filehandle. The *filehandle must
* have been locked before by a call to os_flockfile.
* (not effective on VxWorks DKM platform)
*
* Precondition:
* none
*
* Possible results:
* - No error information is returned.
* The behaviour is undefined if a thread other than the current owner calls
* the os_funlockfile() function.
*
*/
OSAPI_EXPORT void os_funlockfile(
FILE *file);
/**
* \brief binary search algorithm on an already sorted list.
*

View file

@ -37,7 +37,6 @@ extern "C" {
OS_THREAD_WARNING,
OS_THREAD_ALLOCATOR_STATE,
OS_THREAD_NAME,
OS_THREAD_REPORT_STACK,
OS_THREAD_PROCESS_INFO,
OS_THREAD_STATE, /* Used for monitoring thread progress */
OS_THREAD_STR_ERROR,

298
src/os/src/os_log.c Normal file
View file

@ -0,0 +1,298 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "os/os.h"
#define MAX_TIMESTAMP_LEN (10 + 1 + 6)
#define MAX_TID_LEN (10)
#define HDR_LEN (MAX_TIMESTAMP_LEN + 1 + MAX_TID_LEN + 2)
#define BUF_OFFSET HDR_LEN
typedef struct {
char buf[2048];
size_t bufsz;
size_t pos;
} log_buffer_t;
typedef struct {
dds_log_write_fn_t funcs[2];
void *ptr;
FILE *out;
} log_sink_t;
static os_threadLocal log_buffer_t log_buffer;
static os_once_t lock_inited = OS_ONCE_T_STATIC_INIT;
static os_rwlock lock;
static uint32_t log_mask = DDS_LC_ERROR | DDS_LC_WARNING;
static void default_sink(void *ptr, const dds_log_data_t *data)
{
fwrite(data->message - HDR_LEN, 1, HDR_LEN + data->size + 1, (FILE *)ptr);
fflush((FILE *)ptr);
}
static void nop_sink(void *ptr, const dds_log_data_t *data)
{
(void)ptr;
(void)data;
return;
}
#define LOG (0)
#define TRACE (1)
#define USE (0)
#define SET (1)
static log_sink_t sinks[] = {
/* Log */
{ .funcs = { default_sink, default_sink }, .ptr = NULL, .out = NULL },
/* Trace */
{ .funcs = { nop_sink, default_sink }, .ptr = NULL, .out = NULL }
};
uint32_t *const dds_log_mask = &log_mask;
#define RDLOCK (1)
#define WRLOCK (2)
static void init_lock(void)
{
os_rwlockInit(&lock);
sinks[LOG].ptr = sinks[TRACE].ptr = stderr;
sinks[LOG].out = sinks[TRACE].out = stderr;
}
static void lock_sink(int type)
{
assert(type == RDLOCK || type == WRLOCK);
os_once(&lock_inited, &init_lock);
if (type == RDLOCK) {
os_rwlockRead(&lock);
} else {
os_rwlockWrite(&lock);
}
}
static void unlock_sink(void)
{
os_rwlockUnlock(&lock);
}
static void set_active_log_sinks(void)
{
if (dds_get_log_mask() & DDS_LOG_MASK) {
sinks[LOG].funcs[USE] = sinks[LOG].funcs[SET];
} else {
sinks[LOG].funcs[USE] = nop_sink;
}
if (dds_get_log_mask() & DDS_TRACE_MASK) {
sinks[TRACE].funcs[USE] = sinks[TRACE].funcs[SET];
} else {
sinks[TRACE].funcs[USE] = nop_sink;
}
if (sinks[LOG].funcs[USE] == sinks[TRACE].funcs[USE] &&
sinks[LOG].ptr == sinks[TRACE].ptr)
{
sinks[LOG].funcs[USE] = nop_sink;
}
}
static void
set_log_sink(
_In_ log_sink_t *sink,
_In_opt_ dds_log_write_fn_t func,
_In_opt_ void *ptr)
{
assert(sink != NULL);
/* No life cycle management is done for log sinks, the caller is
responsible for that. Ensure this operation is deterministic and that on
return, no thread in the DDS stack still uses the deprecated sink. */
lock_sink(WRLOCK);
if (func == 0) {
sink->funcs[SET] = default_sink;
sink->ptr = sink->out;
} else {
sink->funcs[SET] = func;
sink->ptr = ptr;
}
set_active_log_sinks();
unlock_sink();
}
/* dds_set_log_file must be considered private. */
void dds_set_log_file(_In_ FILE *file)
{
lock_sink(WRLOCK);
sinks[LOG].out = file;
if (sinks[LOG].funcs[SET] == default_sink) {
sinks[LOG].ptr = sinks[LOG].out;
}
unlock_sink();
}
void dds_set_trace_file(_In_ FILE *file)
{
lock_sink(WRLOCK);
sinks[TRACE].out = file;
if (sinks[TRACE].funcs[SET] == default_sink) {
sinks[TRACE].ptr = sinks[TRACE].out;
}
unlock_sink();
}
void dds_set_log_sink(
_In_opt_ dds_log_write_fn_t callback,
_In_opt_ void *userdata)
{
set_log_sink(&sinks[LOG], callback, userdata);
}
void dds_set_trace_sink(
_In_opt_ dds_log_write_fn_t callback,
_In_opt_ void *userdata)
{
set_log_sink(&sinks[TRACE], callback, userdata);
}
extern inline uint32_t
dds_get_log_mask(void);
void
dds_set_log_mask(_In_ uint32_t cats)
{
lock_sink(WRLOCK);
*dds_log_mask = (cats & (DDS_LOG_MASK | DDS_TRACE_MASK));
set_active_log_sinks();
unlock_sink();
}
static void print_header(char *str)
{
int cnt;
char *tid, buf[MAX_TID_LEN] = { 0 };
static const char fmt[] = "%10u.%06d/%*.*s:";
os_time tv;
unsigned sec;
int usec;
(void)os_threadGetThreadName(buf, sizeof(buf));
tid = (buf[0] == '\0' ? "(anon)" : buf);
tv = os_timeGet();
sec = (unsigned)tv.tv_sec;
usec = (int)(tv.tv_nsec / 1000);
cnt = snprintf(
str, HDR_LEN, fmt, sec, usec, MAX_TID_LEN, MAX_TID_LEN, tid);
assert(cnt == (HDR_LEN - 1));
str[cnt] = ' '; /* Replace snprintf null byte by space. */
}
static void vlog(
_In_ uint32_t cat,
_In_z_ const char *file,
_In_ uint32_t line,
_In_z_ const char *func,
_In_z_ const char *fmt,
va_list ap)
{
int n, trunc = 0;
size_t nrem;
log_buffer_t *lb;
dds_log_data_t data;
if (*fmt == 0) {
return;
}
lock_sink(RDLOCK);
lb = &log_buffer;
/* Thread-local buffer is always initialized with all zeroes. The pos
member must always be greater or equal to BUF_OFFSET. */
if (lb->pos < BUF_OFFSET) {
lb->pos = BUF_OFFSET;
lb->buf[lb->pos] = 0;
}
nrem = lb->bufsz - lb->pos;
if (nrem > 0) {
n = os_vsnprintf(lb->buf + lb->pos, nrem, fmt, ap);
if (n >= 0 && (size_t) n < nrem) {
lb->pos += (size_t) n;
} else {
lb->pos += nrem;
trunc = 1;
}
if (trunc) {
static const char msg[] = "(trunc)\n";
const size_t msglen = sizeof (msg) - 1;
assert(lb->pos <= lb->bufsz);
assert(lb->pos >= msglen);
memcpy(lb->buf + lb->pos - msglen, msg, msglen);
}
}
if (fmt[strlen (fmt) - 1] == '\n') {
print_header(lb->buf);
data.priority = cat;
data.file = file;
data.function = func;
data.line = line;
data.message = lb->buf + BUF_OFFSET;
data.size = strlen(data.message) - 1;
for (size_t i = (cat & DDS_LOG_MASK) ? LOG : TRACE;
i < sizeof(sinks) / sizeof(sinks[0]);
i++)
{
sinks[i].funcs[USE](sinks[i].ptr, &data);
}
lb->pos = BUF_OFFSET;
lb->buf[lb->pos] = 0;
}
unlock_sink();
}
int
dds_log(
_In_ uint32_t cat,
_In_z_ const char *file,
_In_ uint32_t line,
_In_z_ const char *func,
_In_z_ _Printf_format_string_ const char *fmt,
...)
{
if ((dds_get_log_mask() & cat) || (cat & DDS_LC_FATAL)) {
va_list ap;
va_start(ap, fmt);
vlog(cat, file, line, func, fmt, ap);
va_end(ap);
}
if (cat & DDS_LC_FATAL) {
abort();
}
return 0;
}

View file

@ -1,909 +0,0 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifdef PIKEOS_POSIX
#include <lwip_config.h>
#endif
#include "os/os.h"
#include "os/os_project.h"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#define OS_REPORT_TYPE_DEBUG (1u)
#define OS_REPORT_TYPE_WARNING (1u<<OS_REPORT_WARNING)
#define OS_REPORT_TYPE_ERROR (1u<<OS_REPORT_ERROR)
#define OS_REPORT_TYPE_CRITICAL (1u<<OS_REPORT_CRITICAL)
#define OS_REPORT_TYPE_FATAL (1u<<OS_REPORT_FATAL)
#define OS_REPORT_TYPE_INFO (1u<<OS_REPORT_INFO)
#define OS_REPORT_TYPE_FLAG(x) (1u<<(x))
#define OS_REPORT_IS_ALWAYS(x) ((x) & (OS_REPORT_TYPE_CRITICAL | OS_REPORT_TYPE_FATAL))
#define OS_REPORT_IS_WARNING(x) ((x) & OS_REPORT_TYPE_WARNING)
#define OS_REPORT_IS_ERROR(x) ((x) & (OS_REPORT_TYPE_ERROR | OS_REPORT_TYPE_CRITICAL | OS_REPORT_TYPE_FATAL))
#define OS_REPORT_FLAG_TYPE(x) (((x) & OS_REPORT_TYPE_FATAL) ? OS_REPORT_FATAL : \
((x) & OS_REPORT_TYPE_CRITICAL) ? OS_REPORT_CRITICAL : \
((x) & OS_REPORT_TYPE_ERROR) ? OS_REPORT_ERROR : \
((x) & OS_REPORT_TYPE_WARNING) ? OS_REPORT_WARNING : \
((x) & OS_REPORT_TYPE_INFO) ? OS_REPORT_INFO : \
((x) & OS_REPORT_TYPE_DEBUG) ? OS_REPORT_DEBUG : \
OS_REPORT_NONE)
#define MAX_FILE_PATH 2048
typedef struct os_reportStack_s {
int count;
unsigned typeset;
const char *file;
int lineno;
const char *signature;
os_iter *reports; /* os_reportEventV1 */
} *os_reportStack;
/**
* The information that is made available to a plugged in logger
* via its TypedReport symbol.
*/
struct os_reportEventV1_s
{
/** The version of this struct i.e. 1. */
uint32_t version;
/** The type / level of this report.
* @see os_reportType */
os_reportType reportType;
/** Context information relating to where the even was generated.
* May contain a function or compnent name or a stacktrace */
char* reportContext;
/** The source file name where the report even was generated */
char* fileName;
/** The source file line number where the report was generated */
int32_t lineNo;
/** An integer code associated with the event. */
int32_t code;
/** A description of the reported event */
char *description;
/** A string identifying the thread the event occurred in */
char* threadDesc;
/** A string identifying the process the event occurred in */
char* processDesc;
};
#define OS_REPORT_EVENT_V1 1
typedef struct os_reportEventV1_s* os_reportEventV1;
static void os__report_append(_Inout_ os_reportStack _this, _In_ const os_reportEventV1 report);
static void os__report_fprintf(_Inout_ FILE *file, _In_z_ _Printf_format_string_ const char *format, ...);
static void os__report_free(_In_ _Post_invalid_ os_reportEventV1 report);
static void os__report_dumpStack(_In_z_ const char *context, _In_z_ const char *path, _In_ int line);
static FILE* error_log = NULL;
static FILE* info_log = NULL;
static os_mutex reportMutex;
static os_mutex infologcreateMutex;
static os_mutex errorlogcreateMutex;
static bool inited = false;
static bool StaleLogsRemoved = false;
/**
* Process global verbosity level for OS_REPORT output. os_reportType
* values >= this value will be written.
* This value defaults to OS_REPORT_INFO, meaning that all types 'above' (i.e.
* other than) OS_REPORT_DEBUG will be written and OS_REPORT_DEBUG will not be.
*/
os_reportType os_reportVerbosity = OS_REPORT_INFO;
/**
* Labels corresponding to os_reportType values.
* @see os_reportType
*/
const char *os_reportTypeText [] = {
"DEBUG",
"INFO",
"WARNING",
"ERROR",
"CRITICAL",
"FATAL",
"NONE"
};
enum os_report_logType {
OS_REPORT_INFO_LOG,
OS_REPORT_ERROR_LOG
};
static char * os_report_defaultInfoFileName = OS_PROJECT_NAME_NOSPACE_SMALL"-info.log";
static char * os_report_defaultErrorFileName = OS_PROJECT_NAME_NOSPACE_SMALL"-error.log";
static const char os_env_logdir[] = OS_PROJECT_NAME_NOSPACE_CAPS"_LOGPATH";
static const char os_env_infofile[] = OS_PROJECT_NAME_NOSPACE_CAPS"_INFOFILE";
static const char os_env_errorfile[] = OS_PROJECT_NAME_NOSPACE_CAPS"_ERRORFILE";
static const char os_env_verbosity[] = OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY";
static const char os_env_append[] = OS_PROJECT_NAME_NOSPACE_CAPS"_LOGAPPEND";
#if defined _WRS_KERNEL
static const char os_default_logdir[] = "/tgtsvr";
#else
static const char os_default_logdir[] = ".";
#endif
static _Ret_maybenull_ FILE *
os__open_file (
_In_z_ const char * file_name)
{
FILE *logfile=NULL;
const char *dir = os_getenv (os_env_logdir);
char * nomalized_dir;
char *str;
size_t len;
os_result res = os_resultSuccess;
if (dir == NULL) {
dir = os_default_logdir;
}
len = strlen (dir) + 2; /* '/' + '\0' */
str = os_malloc (len);
if (str != NULL) {
(void)snprintf (str, len, "%s/", dir);
nomalized_dir = os_fileNormalize (str);
os_free (str);
if (nomalized_dir == NULL) {
res = os_resultFail;
}
os_free(nomalized_dir);
} else {
res = os_resultFail;
}
if (res == os_resultSuccess) {
logfile = fopen (file_name, "a");
}
return logfile;
}
static void
os__close_file (
_In_z_ const char * file_name,
_In_ _Post_invalid_ FILE *file)
{
if (strcmp(file_name, "<stderr>") != 0 && strcmp(file_name, "<stdout>") != 0)
{
fclose(file);
}
}
_Check_return_ _Ret_z_
static char *os__report_createFileNormalize(
_In_z_ const char *file_dir,
_In_z_ const char *file_name)
{
char file_path[MAX_FILE_PATH];
int len;
len = snprintf(file_path, MAX_FILE_PATH, "%s/%s", file_dir, file_name);
/* Note bug in glibc < 2.0.6 returns -1 for output truncated */
if ( len < MAX_FILE_PATH && len > -1 ) {
return (os_fileNormalize(file_path));
} else {
return os_strdup(file_name);
}
}
/**
* Return either a log file path string or a pseudo file name/path value
* like <stdout> or <stderr>.
* The result of os_report_file_path must be freed with os_free
* @param override_variable An environment variable name that may hold a filename
* or pseudo filename. If this var is set, and is not a pseudo filename,
* the value of this var will be added to the value of env variable
* {OS_PROJECT_NAME_NOSPACE_CAPS}_LOGPATH (if set or './' if not) to create the
* log file path.
* @param default_file If override_variable is not defined in the environment
* this is the filename used.
*/
_Ret_z_
_Check_return_
static char *
os__report_file_path(
_In_z_ const char * default_file,
_In_opt_z_ const char * override_variable,
_In_ enum os_report_logType type)
{
const char *file_dir;
const char *file_name = NULL;
if (override_variable != NULL)
{
file_name = os_getenv(override_variable);
}
if (!file_name)
{
file_name = default_file;
}
file_dir = os_getenv(os_env_logdir);
if (!file_dir)
{
file_dir = os_default_logdir;
}
else
{
/* We just need to check if a file can be written to the directory, we just use the
* default info file as there will always be one created, if we used the variables
* passed in we would create an empty error log (which is bad for testing) and we
* cannot delete it as we open the file with append
*/
if (type == OS_REPORT_INFO_LOG)
{
FILE *logfile;
char *full_file_path;
full_file_path = os_malloc(strlen(file_dir) + 1 + strlen(file_name) + 1);
strcpy(full_file_path, file_dir);
strcat(full_file_path, "/");
strcat(full_file_path, file_name);
logfile = fopen (full_file_path, "a");
if (logfile)
{
fclose(logfile);
}
os_free (full_file_path);
}
}
if (strcmp(file_name, "<stderr>") != 0 && strcmp(file_name, "<stdout>") != 0)
{
return (os__report_createFileNormalize(file_dir, file_name));
}
return os_strdup (file_name);
}
/**
* Overrides the current minimum output level to be reported from
* this process.
* @param newVerbosity String holding either an integer value corresponding
* to an acceptable (in range) log verbosity or a string verbosity 'name'
* like 'ERROR' or 'warning' or 'DEBUG' or somesuch.
* @return os_resultFail if the string contains neither of the above;
* os_resultSuccess otherwise.
*/
static os_result
os__determine_verbosity(
_In_z_ const char* newVerbosity)
{
long verbosityInt;
os_result result = os_resultFail;
verbosityInt = strtol(newVerbosity, NULL, 0);
if (verbosityInt == 0 && strcmp("0", newVerbosity)) {
/* Conversion from int failed. See if it's one of the string forms. */
while (verbosityInt < (long) (sizeof(os_reportTypeText) / sizeof(os_reportTypeText[0]))) {
if (os_strcasecmp(newVerbosity, os_reportTypeText[verbosityInt]) == 0) {
break;
}
++verbosityInt;
}
}
if (verbosityInt >= 0 && verbosityInt < (long) (sizeof(os_reportTypeText) / sizeof(os_reportTypeText[0]))) {
/* OS_API_INFO label is kept for backwards compatibility. */
os_reportVerbosity = (os_reportType)verbosityInt;
result = os_resultSuccess;
}
return result;
}
void os__set_verbosity(void)
{
const char * envValue = os_getenv(os_env_verbosity);
if (envValue != NULL)
{
if (os__determine_verbosity(envValue) == os_resultFail)
{
OS_WARNING("os_reportInit", 0,
"Cannot parse report verbosity %s value \"%s\","
" reporting verbosity remains %s", os_env_verbosity, envValue, os_reportTypeText[os_reportVerbosity]);
}
}
}
/**
* Get the destination for logging error reports. Env property {OS_PROJECT_NAME_NOSPACE_CAPS}_INFOFILE and
* {OS_PROJECT_NAME_NOSPACE_CAPS}_LOGPATH controls this value.
* If {OS_PROJECT_NAME_NOSPACE_CAPS}_INFOFILE is not set & this process is a service, default
* to logging to a file named {OS_PROJECT_NAME_NOSPACE_SMALL}-info.log, otherwise
* use standard out.
* @see os_report_file_path
*/
_Ret_z_
_Check_return_
static char *
os__get_info_file_name(void)
{
char * file_name;
os_mutexLock(&infologcreateMutex);
file_name = os__report_file_path (os_report_defaultInfoFileName, os_env_infofile, OS_REPORT_INFO_LOG);
os_mutexUnlock(&infologcreateMutex);
return file_name;
}
/**
* Get the destination for logging error reports. Env property {OS_PROJECT_NAME_NOSPACE_CAPS}_ERRORFILE and
* {OS_PROJECT_NAME_NOSPACE_CAPS}_LOGPATH controls this value.
* If {OS_PROJECT_NAME_NOSPACE_CAPS}_ERRORFILE is not set & this process is a service, default
* to logging to a file named {OS_PROJECT_NAME_NOSPACE_SMALL}-error.log, otherwise
* use standard error.
* @see os_report_file_path
*/
_Ret_z_
_Check_return_
static char *
os__get_error_file_name(void)
{
char * file_name;
os_mutexLock(&errorlogcreateMutex);
file_name = os__report_file_path (os_report_defaultErrorFileName, os_env_errorfile, OS_REPORT_ERROR_LOG);
os_mutexUnlock(&errorlogcreateMutex);
return file_name;
}
static void os__remove_stale_logs(void)
{
if (!StaleLogsRemoved) {
/* TODO: Only a single process or spliced (as 1st process) is allowed to
* delete the log files. */
/* Remove ospl-info.log and ospl-error.log.
* Ignore the result because it is possible that they don't exist yet. */
char * log_file_name;
log_file_name = os__get_error_file_name();
(void)os_remove(log_file_name);
os_free(log_file_name);
log_file_name = os__get_info_file_name();
(void)os_remove(log_file_name);
os_free(log_file_name);
StaleLogsRemoved = true;
}
}
static void os__check_removal_stale_logs(void)
{
const char * envValue = os_getenv(os_env_append);
if (envValue != NULL)
{
if (os_strcasecmp(envValue, "FALSE") == 0 ||
os_strcasecmp(envValue, "0") == 0 ||
- os_strcasecmp(envValue, "NO") == 0) {
os__remove_stale_logs();
}
}
}
/**
* Read environment properties. In particular ones that can't be left until
* there is a requirement to log.
*/
void os_reportInit(
_In_ bool forceReInit)
{
if (forceReInit) {
inited = false;
}
if (!inited)
{
os_mutexInit(&reportMutex);
os_mutexInit(&errorlogcreateMutex);
os_mutexInit(&infologcreateMutex);
os__check_removal_stale_logs();
os__set_verbosity();
}
inited = true;
}
void os_reportExit(void)
{
char *name;
os_reportStack reports;
if (!inited) {
return;
}
reports = os_threadMemGet(OS_THREAD_REPORT_STACK);
if (reports) {
os__report_dumpStack(OS_FUNCTION, __FILE__, __LINE__);
os_iterFree(reports->reports, NULL);
os_threadMemFree(OS_THREAD_REPORT_STACK);
}
inited = false;
os_mutexDestroy(&reportMutex);
if (error_log)
{
name = os__get_error_file_name();
os__close_file(name, error_log);
os_free (name);
error_log = NULL;
}
if (info_log)
{
name = os__get_info_file_name();
os__close_file(name, info_log);
os_free (name);
info_log = NULL;
}
os_mutexDestroy(&errorlogcreateMutex);
os_mutexDestroy(&infologcreateMutex);
}
static void os__report_fprintf(
_Inout_ FILE *file,
_In_z_ _Printf_format_string_ const char *format, ...)
{
int BytesWritten = 0;
va_list args;
va_start(args, format);
BytesWritten = os_vfprintfnosigpipe(file, format, args);
va_end(args);
if (BytesWritten == -1) {
/* error occurred ?, try to write to stdout. (also with no sigpipe,
* stdout can also give broken pipe)
*/
va_start(args, format);
(void) os_vfprintfnosigpipe(stdout, format, args);
va_end(args);
}
}
static _Ret_notnull_ FILE* os__get_info_file (void)
{
if (info_log == NULL) {
char * name = os__get_info_file_name();
info_log = os__open_file(name);
if (!info_log)
{
info_log = stdout;
}
os_free (name);
}
return info_log;
}
static _Ret_notnull_ FILE* os__get_error_file (void)
{
if (error_log == NULL) {
char * name = os__get_error_file_name();
error_log = os__open_file(name);
if (!error_log)
{
error_log = stderr;
}
os_free (name);
}
return error_log;
}
static void os__sectionReport(
_Pre_notnull_ _Post_notnull_ os_reportEventV1 event,
_In_ bool useErrorLog)
{
os_time ostime;
FILE *log = useErrorLog ? os__get_error_file() : os__get_info_file();
ostime = os_timeGet();
os_mutexLock(&reportMutex);
os__report_fprintf(log,
"----------------------------------------------------------------------------------------\n"
"Report : %s\n"
"Internals : %s/%s/%d/%d/%d.%09d\n",
event->description,
event->reportContext,
event->fileName,
event->lineNo,
event->code,
ostime.tv_sec,
ostime.tv_nsec);
fflush (log);
os_mutexUnlock(&reportMutex);
}
static void os__headerReport(
_Pre_notnull_ _Post_notnull_ os_reportEventV1 event,
_In_ bool useErrorLog)
{
os_time ostime;
char node[64];
char date_time[128];
FILE *log = NULL;
if (useErrorLog)
log = os__get_error_file();
else log = os__get_info_file();
ostime = os_timeGet();
os_ctime_r(&ostime, date_time, sizeof(date_time));
if (os_gethostname(node, sizeof(node)-1) == os_resultSuccess)
{
node[sizeof(node)-1] = '\0';
}
else
{
strcpy(node, "UnkownNode");
}
os_mutexLock(&reportMutex);
os__report_fprintf(log,
"========================================================================================\n"
"ReportType : %s\n"
"Context : %s\n"
"Date : %s\n"
"Node : %s\n"
"Process : %s\n"
"Thread : %s\n"
"Internals : %s/%d/%s/%s/%s\n",
os_reportTypeText[event->reportType],
event->description,
date_time,
node,
event->processDesc,
event->threadDesc,
event->fileName,
event->lineNo,
OSPL_VERSION_STR,
OSPL_INNER_REV_STR,
OSPL_OUTER_REV_STR);
fflush (log);
os_mutexUnlock(&reportMutex);
}
static void os__defaultReport(
_Pre_notnull_ _Post_notnull_ os_reportEventV1 event)
{
os_time ostime;
char node[64];
char date_time[128];
FILE *log;
switch (event->reportType) {
case OS_REPORT_DEBUG:
case OS_REPORT_INFO:
case OS_REPORT_WARNING:
log = os__get_info_file();
break;
case OS_REPORT_ERROR:
case OS_REPORT_CRITICAL:
case OS_REPORT_FATAL:
default:
log = os__get_error_file();
break;
}
ostime = os_timeGet();
os_ctime_r(&ostime, date_time, sizeof(date_time));
if (os_gethostname(node, sizeof(node)-1) == os_resultSuccess)
{
node[sizeof(node)-1] = '\0';
}
else
{
strcpy(node, "UnkownNode");
}
os_mutexLock(&reportMutex);
os__report_fprintf (log,
"========================================================================================\n"
"Report : %s\n"
"Date : %s\n"
"Description : %s\n"
"Node : %s\n"
"Process : %s\n"
"Thread : %s\n"
"Internals : %s/%s/%s/%s/%s/%d/%d/%d.%09d\n",
os_reportTypeText[event->reportType],
date_time,
event->description,
node,
event->processDesc,
event->threadDesc,
OSPL_VERSION_STR,
OSPL_INNER_REV_STR,
OSPL_OUTER_REV_STR,
event->reportContext,
event->fileName,
event->lineNo,
event->code,
ostime.tv_sec,
ostime.tv_nsec);
fflush (log);
os_mutexUnlock(&reportMutex);
}
void os_report_message(
_In_ os_reportType type,
_In_z_ const char *context,
_In_z_ const char *path,
_In_ int32_t line,
_In_ int32_t code,
_In_z_ const char *message)
{
char *file;
char procid[256], thrid[64];
os_reportStack stack;
struct os_reportEventV1_s report = { OS_REPORT_EVENT_V1, /* version */
OS_REPORT_NONE, /* reportType */
NULL, /* reportContext */
NULL, /* fileName */
0, /* lineNo */
0, /* code */
NULL, /* description */
NULL, /* threadDesc */
NULL /* processDesc */
};
file = (char *)path;
/* Only figure out process and thread identities if the user requested an
entry in the default log file or registered a typed report plugin. */
os_procNamePid (procid, sizeof (procid));
os_threadFigureIdentity (thrid, sizeof (thrid));
report.reportType = type;
report.reportContext = (char *)context;
report.fileName = (char *)file;
report.lineNo = line;
report.code = code;
report.description = (char *)message;
report.threadDesc = thrid;
report.processDesc = procid;
stack = (os_reportStack)os_threadMemGet(OS_THREAD_REPORT_STACK);
if (stack && stack->count) {
if (report.reportType != OS_REPORT_NONE) {
os__report_append (stack, &report);
}
} else {
os__defaultReport (&report);
}
}
void os_report(
_In_ os_reportType type,
_In_z_ const char *context,
_In_z_ const char *path,
_In_ int32_t line,
_In_ int32_t code,
_In_z_ _Printf_format_string_ const char *format,
...)
{
char buf[OS_REPORT_BUFLEN];
va_list args;
if (!inited) {
return;
}
if (type < os_reportVerbosity) {
return;
}
va_start (args, format);
(void)os_vsnprintf (buf, sizeof(buf), format, args);
va_end (args);
os_report_message(type, context, path, line, code, buf);
}
/*****************************************
* Report-stack related functions
*****************************************/
void os_report_stack(void)
{
os_reportStack _this;
if (inited == false) {
return;
}
_this = (os_reportStack)os_threadMemGet(OS_THREAD_REPORT_STACK);
if (!_this) {
/* Report stack does not exist yet, so create it */
_this = os_threadMemMalloc(OS_THREAD_REPORT_STACK, sizeof(struct os_reportStack_s));
if (_this) {
_this->count = 1;
_this->typeset = 0;
_this->file = NULL;
_this->lineno = 0;
_this->signature = NULL;
_this->reports = os_iterNew();
} else {
OS_ERROR("os_report_stack", 0,
"Failed to initialize report stack (could not allocate thread-specific memory)");
}
} else {
/* Use previously created report stack */
if (_this->count == 0) {
_this->file = NULL;
_this->lineno = 0;
_this->signature = NULL;
}
_this->count++;
}
}
void os_report_stack_free(void)
{
os_reportStack _this;
os_reportEventV1 report;
_this = (os_reportStack)os_threadMemGet(OS_THREAD_REPORT_STACK);
if (_this) {
while((report = os_iterTake(_this->reports, -1))) {
os__report_free(report);
}
os_iterFree(_this->reports, NULL);
os_threadMemFree(OS_THREAD_REPORT_STACK);
}
}
static void
os__report_stack_unwind(
_Inout_ os_reportStack _this,
_In_ bool valid,
_In_z_ const char *context,
_In_z_ const char *path,
_In_ int line)
{
struct os_reportEventV1_s header;
os_reportEventV1 report;
char *file;
bool useErrorLog;
os_reportType reportType = OS_REPORT_ERROR;
if (!valid) {
if (OS_REPORT_IS_ALWAYS(_this->typeset)) {
valid = true;
}
} else {
reportType = OS_REPORT_FLAG_TYPE(_this->typeset);
}
useErrorLog = OS_REPORT_IS_ERROR(_this->typeset);
/* Typeset will be set when a report was appended. */
if (valid && (_this->typeset != 0)) {
char proc[256], procid[256];
char thr[64], thrid[64];
assert (context != NULL);
assert (path != NULL);
file = (char *)path;
os_procNamePid (procid, sizeof (procid));
os_procName (proc, sizeof (proc));
os_threadFigureIdentity (thrid, sizeof (thrid));
os_threadGetThreadName (thr, sizeof (thr));
header.reportType = reportType;
header.description = (char *)context;
header.processDesc = procid;
header.threadDesc = thrid;
header.fileName = file;
header.lineNo = line;
os__headerReport (&header, useErrorLog);
}
while ((report = os_iterTake(_this->reports, -1))) {
if (valid) {
os__sectionReport (report, useErrorLog);
}
os__report_free(report);
}
_this->typeset = 0;
}
static void
os__report_dumpStack(
_In_z_ const char *context,
_In_z_ const char *path,
_In_ int line)
{
os_reportStack _this;
if (inited == false) {
return;
}
_this = os_threadMemGet(OS_THREAD_REPORT_STACK);
if ((_this) && (_this->count > 0)) {
os__report_stack_unwind(_this, true, context, path, line);
}
}
void os_report_flush(
_In_ bool valid,
_In_z_ const char *context,
_In_z_ const char *path,
_In_ int line)
{
os_reportStack _this;
if (inited == false) {
return;
}
_this = os_threadMemGet(OS_THREAD_REPORT_STACK);
if ((_this) && (_this->count)) {
if (_this->count == 1) {
os__report_stack_unwind(_this, valid, context, path, line);
_this->file = NULL;
_this->signature = NULL;
_this->lineno = 0;
}
_this->count--;
}
}
#define OS__STRDUP(str) (str != NULL ? os_strdup(str) : os_strdup("NULL"))
static void
os__report_append(
_Inout_ os_reportStack _this,
_In_ const os_reportEventV1 report)
{
os_reportEventV1 copy;
copy = os_malloc(sizeof(*copy));
copy->code = report->code;
copy->description = OS__STRDUP(report->description);
copy->fileName = OS__STRDUP(report->fileName);
copy->lineNo = report->lineNo;
copy->processDesc = OS__STRDUP(report->processDesc);
copy->reportContext = OS__STRDUP(report->reportContext);
copy->reportType = report->reportType;
copy->threadDesc = OS__STRDUP(report->threadDesc);
copy->version = report->version;
_this->typeset |= OS_REPORT_TYPE_FLAG(report->reportType);
os_iterAppend(_this->reports, copy);
}
static void
os__report_free(
_In_ _Post_invalid_ os_reportEventV1 report)
{
os_free(report->description);
os_free(report->fileName);
os_free(report->processDesc);
os_free(report->reportContext);
os_free(report->threadDesc);
os_free(report);
}

View file

@ -256,13 +256,13 @@ os_sockaddrStringToAddress(
ret = getaddrinfo(addressString, NULL, &hints, &res);
if (ret != 0) {
fmt = "getaddrinfo(\"%s\") failed: %s";
OS_DEBUG(OS_FUNCTION, 0, fmt, addressString, os_gai_strerror(ret));
DDS_TRACE(fmt, addressString, os_gai_strerror(ret));
} else if (res != NULL) {
memcpy(addressOut, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
} else {
fmt = "getaddrinfo(\"%s\") did not return any results";
OS_DEBUG(OS_FUNCTION, 0, fmt, addressString);
DDS_TRACE(fmt, addressString);
}
return (ret == 0 && res != NULL);

View file

@ -37,3 +37,32 @@ os_threadAttrInit (
threadAttr->schedPriority = 0;
threadAttr->stackSize = 0;
}
int32_t
os_threadFigureIdentity(char *str, uint32_t size)
{
int32_t cnt;
uintmax_t id;
char *fmt, *ptr, buf[1] = { '\0' };
uint32_t sz;
assert(str != NULL);
assert(size >= 1);
id = os_threadIdToInteger(os_threadIdSelf());
cnt = os_threadGetThreadName(str, size);
if (cnt >= 0) {
fmt = (cnt > 0 ? " 0x%"PRIxMAX : "0x%"PRIxMAX);
if ((uint32_t)cnt < size) {
ptr = str + (uint32_t)cnt;
sz = size - (uint32_t)cnt;
} else {
ptr = buf;
sz = sizeof(buf);
}
cnt += snprintf(ptr, sz, fmt, id);
}
return cnt;
}

View file

@ -32,14 +32,12 @@ void os_osPlatformInit (void)
os_syncModuleInit();
os_threadModuleInit();
os_processModuleInit();
os_reportInit(false);
}
/** \brief OS layer deinitialization
*/
void os_osPlatformExit (void)
{
os_reportExit();
os_processModuleExit();
os_threadModuleExit();
os_syncModuleExit();

View file

@ -309,6 +309,7 @@ void os_rwlockRead(os_rwlock *rwlock)
err = pthread_rwlock_rdlock(&rwlock->rwlock);
assert(err == 0);
(void)err;
}
void os_rwlockWrite(os_rwlock *rwlock)
@ -319,6 +320,7 @@ void os_rwlockWrite(os_rwlock *rwlock)
err = pthread_rwlock_wrlock(&rwlock->rwlock);
assert(err == 0);
(void)err;
}
os_result os_rwlockTryRead(os_rwlock *rwlock)
@ -353,6 +355,7 @@ void os_rwlockUnlock(os_rwlock *rwlock)
err = pthread_rwlock_unlock(&rwlock->rwlock);
assert(err == 0);
(void)err;
}
void

View file

@ -65,13 +65,12 @@ os_threadMemInit (
if (pthreadMemArray != NULL) {
memset (pthreadMemArray, 0, sizeof(void *) * OS_THREAD_MEM_ARRAY_SIZE);
if (pthread_setspecific (os_threadMemKey, pthreadMemArray) == EINVAL) {
OS_ERROR("os_threadMemInit", 4,
"pthread_setspecific failed with error EINVAL (%d), "
"invalid threadMemKey value", EINVAL);
DDS_ERROR("pthread_setspecific failed with error EINVAL (%d), "
"invalid threadMemKey value\n", EINVAL);
os_free(pthreadMemArray);
}
} else {
OS_ERROR("os_threadMemInit", 3, "Out of heap memory");
DDS_ERROR("Out of heap memory\n");
}
}
@ -106,7 +105,7 @@ os_threadMemExit(
os_free (pthreadMemArray);
pthreadMemArray = NULL;
if (pthread_setspecific (os_threadMemKey, pthreadMemArray) == EINVAL) {
OS_ERROR("os_threadMemExit", 4, "pthread_setspecific failed with error %d", EINVAL);
DDS_ERROR("pthread_setspecific failed with error %d\n", EINVAL);
}
}
}
@ -164,9 +163,8 @@ os_startRoutineWrapper (
/* store the thread name with the thread via thread specific data; failure isn't */
if (pthread_setspecific (os_threadNameKey, context->threadName) == EINVAL) {
OS_WARNING("os_startRoutineWrapper", 0,
"pthread_setspecific failed with error EINVAL (%d), "
"invalid os_threadNameKey value", EINVAL);
DDS_WARNING("pthread_setspecific failed with error EINVAL (%d), "
"invalid os_threadNameKey value\n", EINVAL);
}
/* allocate an array to store thread private memory references */
@ -175,12 +173,10 @@ os_startRoutineWrapper (
/* Call the user routine */
resultValue = context->startRoutine (context->arguments);
os_report_stack_free();
/* Free the thread context resources, arguments is responsibility */
/* for the caller of os_procCreate */
os_free (context->threadName);
os_free (context);
os_free(context->threadName);
os_free(context);
/* deallocate the array to store thread private memory references */
os_threadMemExit ();
@ -276,32 +272,28 @@ os_threadCreate (
if (result != 0) {
char errmsg[64];
(void)os_strerror_r(result, errmsg, sizeof(errmsg));
OS_WARNING("os_threadCreate", 2,
"pthread_attr_setschedpolicy failed for SCHED_FIFO with "\
"error %d (%s) for thread '%s', reverting to SCHED_OTHER.",
result, errmsg, name);
DDS_WARNING("pthread_attr_setschedpolicy failed for SCHED_FIFO with "
"error %d (%s) for thread '%s', reverting to SCHED_OTHER\n",
result, errmsg, name);
result = pthread_attr_setschedpolicy (&attr, SCHED_OTHER);
if (result != 0) {
OS_WARNING("os_threadCreate", 2, "pthread_attr_setschedpolicy failed with error %d (%s)", result, name);
DDS_WARNING("pthread_attr_setschedpolicy failed with error %d (%s)\n", result, name);
}
}
} else {
result = pthread_attr_setschedpolicy (&attr, SCHED_OTHER);
if (result != 0) {
OS_WARNING("os_threadCreate", 2,
"pthread_attr_setschedpolicy failed with error %d (%s)",
result, name);
DDS_WARNING("pthread_attr_setschedpolicy failed with error %d (%s)\n", result, name);
}
}
pthread_attr_getschedpolicy(&attr, &policy);
if ((tattr.schedPriority < sched_get_priority_min(policy)) ||
(tattr.schedPriority > sched_get_priority_max(policy))) {
OS_WARNING("os_threadCreate", 2,
"scheduling priority outside valid range for the policy "\
"reverted to valid value (%s)", name);
DDS_WARNING("scheduling priority outside valid range for the policy "
"reverted to valid value (%s)\n", name);
sched_param.sched_priority = (sched_get_priority_min(policy) +
sched_get_priority_max(policy)) / 2;
} else {
@ -317,9 +309,8 @@ os_threadCreate (
/* start the thread */
result = pthread_attr_setschedparam (&attr, &sched_param);
if (result != 0) {
OS_WARNING("os_threadCreate", 2,
"pthread_attr_setschedparam failed with error %d (%s)",
result, name);
DDS_WARNING("pthread_attr_setschedparam failed with error %d (%s)\n",
result, name);
}
create_ret = pthread_create(&threadId->v, &attr, os_startRoutineWrapper,
@ -330,19 +321,17 @@ os_threadCreate (
*/
if((create_ret == EPERM) && (tattr.schedClass == OS_SCHED_REALTIME))
{
OS_WARNING("os_threadCreate", 2,
"pthread_create failed with SCHED_FIFO " \
"for thread '%s', reverting to SCHED_OTHER.",
name);
DDS_WARNING("pthread_create failed with SCHED_FIFO "
"for thread '%s', reverting to SCHED_OTHER\n",
name);
(void) pthread_attr_setschedpolicy (&attr, SCHED_OTHER); /* SCHED_OTHER is always supported */
pthread_attr_getschedpolicy(&attr, &policy);
if ((tattr.schedPriority < sched_get_priority_min(policy)) ||
(tattr.schedPriority > sched_get_priority_max(policy)))
{
OS_WARNING("os_threadCreate", 2,
"scheduling priority outside valid range for the " \
"policy reverted to valid value (%s)", name);
DDS_WARNING("scheduling priority outside valid range for the "
"policy reverted to valid value (%s)\n", name);
sched_param.sched_priority =
(sched_get_priority_min(policy) +
sched_get_priority_max(policy)) / 2;
@ -352,9 +341,8 @@ os_threadCreate (
result = pthread_attr_setschedparam (&attr, &sched_param);
if (result != 0) {
OS_WARNING("os_threadCreate", 2,
"pthread_attr_setschedparam failed " \
"with error %d (%s)", result, name);
DDS_WARNING("pthread_attr_setschedparam failed "
"with error %d (%s)", result, name);
} else {
create_ret = pthread_create(&threadId->v, &attr,
os_startRoutineWrapper, threadContext);
@ -366,7 +354,7 @@ os_threadCreate (
if(create_ret != 0){
os_free (threadContext->threadName);
os_free (threadContext);
OS_WARNING("os_threadCreate", 2, "pthread_create failed with error %d (%s)", create_ret, name);
DDS_WARNING("pthread_create failed with error %d (%s)\n", create_ret, name);
rv = os_resultFail;
}
}
@ -398,29 +386,6 @@ os_threadIdSelf (void)
return id;
}
/** \brief Figure out the identity of the current thread
*
* \b os_threadFigureIdentity determines the numeric identity
* of a thread. POSIX does not identify threads by name,
* therefore only the numeric identification is returned,
*/
int32_t
os_threadFigureIdentity (
char *threadIdentity,
uint32_t threadIdentitySize)
{
int size;
char *threadName;
threadName = pthread_getspecific (os_threadNameKey);
if (threadName != NULL) {
size = snprintf (threadIdentity, threadIdentitySize, "%s 0x%"PRIxMAX, threadName, (uintmax_t)pthread_self ());
} else {
size = snprintf (threadIdentity, threadIdentitySize, "0x%"PRIxMAX, (uintmax_t)pthread_self ());
}
return size;
}
int32_t
os_threadGetThreadName (
char *buffer,
@ -486,7 +451,7 @@ os_threadWaitExit (
if (result != 0) {
/* NOTE: The below report actually is a debug output; makes no sense from
* a customer perspective. Made OS_INFO for now. */
OS_INFO("os_threadWaitExit", 2, "pthread_join(0x%"PRIxMAX") failed with error %d", os_threadIdToInteger(threadId), result);
DDS_INFO("pthread_join(0x%"PRIxMAX") failed with error %d\n", os_threadIdToInteger(threadId), result);
rv = os_resultFail;
} else {
rv = os_resultSuccess;
@ -652,7 +617,7 @@ os_threadCleanupPush(
itr = os_iterNew();
assert(itr != NULL);
if (pthread_setspecific(cleanup_key, itr) == EINVAL) {
OS_WARNING(OS_FUNCTION, 0, "pthread_setspecific failed with error EINVAL (%d)", EINVAL);
DDS_WARNING("pthread_setspecific failed with error EINVAL (%d)\n", EINVAL);
os_iterFree(itr, NULL);
itr = NULL;
}

View file

@ -62,28 +62,6 @@ os_pathSep(void)
return ":";
}
os_result
os_access(
const char *file_path,
int32_t permission)
{
os_result result;
#ifdef VXWORKS_RTP
/* The access function is broken for vxworks RTP for some filesystems
so best ignore the result, and assume the user has correct permissions */
(void) file_path;
(void) permission;
result = os_resultSuccess;
#else
if (access (file_path, permission) == 0) {
result = os_resultSuccess;
} else {
result = os_resultFail;
}
#endif
return result;
}
int
os_vsnprintf(
char *str,
@ -130,125 +108,11 @@ os_vfprintfnosigpipe(
return result;
}
os_result
os_stat(
const char *path,
struct os_stat *buf)
{
os_result result;
struct stat _buf;
int r;
r = stat(path, &_buf);
if (r == 0) {
buf->stat_mode = _buf.st_mode;
buf->stat_size = (size_t) _buf.st_size;
buf->stat_mtime.tv_sec = (os_timeSec) _buf.st_mtime;
buf->stat_mtime.tv_nsec = 0;
result = os_resultSuccess;
} else {
result = os_resultFail;
}
return result;
}
os_result os_remove (const char *pathname)
{
return (remove (pathname) == 0) ? os_resultSuccess : os_resultFail;
}
os_result os_rename (const char *oldpath, const char *newpath)
{
return (rename (oldpath, newpath) == 0) ? os_resultSuccess : os_resultFail;
}
/* The result of os_fileNormalize should be freed with os_free */
char *
os_fileNormalize(
const char *filepath)
{
char *norm;
const char *fpPtr;
char *normPtr;
norm = NULL;
if ((filepath != NULL) && (*filepath != '\0')) {
norm = os_malloc(strlen(filepath) + 1);
/* replace any / or \ by OS_FILESEPCHAR */
fpPtr = (char *) filepath;
normPtr = norm;
while (*fpPtr != '\0') {
*normPtr = *fpPtr;
if ((*fpPtr == '/') || (*fpPtr == '\\')) {
*normPtr = OS_FILESEPCHAR;
normPtr++;
} else {
if (*fpPtr != '\"') {
normPtr++;
}
}
fpPtr++;
}
*normPtr = '\0';
}
return norm;
}
os_result
os_fsync(
FILE *fHandle)
{
os_result r;
if (fsync(fileno(fHandle)) == 0) {
r = os_resultSuccess;
} else {
r = os_resultFail;
}
return r;
}
_Ret_opt_z_ const char *
os_getTempDir(void)
{
const char * dir_name = NULL;
dir_name = os_getenv("OSPL_TEMP");
/* if OSPL_TEMP is not defined the default is /tmp */
if (dir_name == NULL || (strcmp (dir_name, "") == 0)) {
dir_name = "/tmp";
}
return dir_name;
}
ssize_t os_write(int fd, const void *buf, size_t count)
{
return write(fd, buf, count);
}
void os_flockfile(FILE *file)
{
/* flockfile is not supported on the VxWorks DKM platform.
* Therefore, this function block is empty on the VxWorks platform. */
#ifndef _WRS_KERNEL
flockfile (file);
#endif
}
void os_funlockfile(FILE *file)
{
/* funlockfile is not supported on the VxWorks DKM platform.
* Therefore, this function block is empty on the VxWorks platform. */
#ifndef _WRS_KERNEL
funlockfile (file);
#endif
}
int os_getopt(int argc, char **argv, const char *opts)
{
return getopt(argc, argv, opts);

View file

@ -23,8 +23,6 @@
* independent conversions.
*/
#include "os/os_report.h"
/*
* Determine the maximum size that a string should have to be
* able to contain a double.
@ -76,9 +74,8 @@ os_lcNumericGet(void)
(void) snprintf(num, 4, "%3.1f", 2.2);
lcNumeric = num [1];
if (lcNumeric != '.') {
OS_WARNING("os_stdlib", 0,
"Locale with LC_NUMERIC \'%c\' detected, which is not '.'. This can decrease performance.",
lcNumeric);
DDS_WARNING("Locale with LC_NUMERIC \'%c\' detected, which is not '.'. "
"This can decrease performance.", lcNumeric);
}
}

View file

@ -84,7 +84,7 @@ void os_osExit (void)
uint32_t initCount;
#if defined(OS_USE_ALLIGNED_MALLOC) && !defined(NDEBUG)
OS_INFO("os__reallocdoublecopycount", 0, "count=%d", vxAtomicGet(&os__reallocdoublecopycount));
DDS_INFO("count=%d\n", vxAtomicGet(&os__reallocdoublecopycount));
#endif
initCount = os_atomic_dec32_nv(&_ospl_osInitCount);
@ -96,7 +96,7 @@ void os_osExit (void)
/* The 0 boundary is passed, so os_osExit is called more often than
* os_osInit. Therefore undo decrement as nothing happened and warn. */
initCount = os_atomic_inc32_nv(&_ospl_osInitCount);
OS_WARNING("os_osExit", 1, "OS-layer not initialized");
DDS_WARNING("OS-layer not initialized\n");
/* Fail in case of DEV, as it is incorrect API usage */
assert(0);
}

View file

@ -26,14 +26,12 @@ void os_osPlatformInit (void)
os_processModuleInit();
os_threadModuleInit();
os_timeModuleInit();
os_reportInit(false);
os_socketModuleInit();
}
void os_osPlatformExit (void)
{
os_socketModuleExit();
os_reportExit();
os_timeModuleExit();
os_threadModuleExit();
os_processModuleExit();

View file

@ -58,7 +58,7 @@ os_socketModuleInit()
err = WSAStartup (wVersionRequested, &wsaData);
if (err != 0) {
OS_FATAL("os_socketModuleInit", 0, "WSAStartup failed, no compatible socket implementation available");
DDS_FATAL("WSAStartup failed, no compatible socket implementation available\n");
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
return;
@ -74,14 +74,14 @@ os_socketModuleInit()
(HIBYTE(wsaData.wVersion) != OS_SOCK_REVISION)) {
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
OS_FATAL("os_socketModuleInit", 1, "WSAStartup failed, no compatible socket implementation available");
DDS_FATAL("WSAStartup failed, no compatible socket implementation available\n");
WSACleanup();
return;
}
qwaveDLLModuleLock = CreateMutex(NULL, FALSE, NULL);
if (qwaveDLLModuleLock == NULL) {
OS_ERROR("os_socketModuleInit", 0, "Failed to create mutex");
DDS_ERROR("Failed to create mutex\n");
}
}
@ -232,7 +232,7 @@ os_sockSetDscpValueWithTos(
char errmsg[1024];
int errNo = os_getErrno();
(void) os_strerror_r(errNo, errmsg, sizeof errmsg);
OS_WARNING("os_sockSetDscpValue", 0, "Failed to set diffserv value to %lu: %d %s", value, errNo, errmsg);
DDS_WARNING("Failed to set diffserv value to %lu: %d %s\n", value, errNo, errmsg);
result = os_resultFail;
}
@ -244,16 +244,14 @@ static os_result
os_sockLoadQwaveLibrary(void)
{
if (qwaveDLLModuleLock == NULL) {
OS_WARNING("os_sockLoadQwaveLibrary", 0,
"Failed to load QWAVE.DLL for using diffserv on outgoing IP packets");
DDS_WARNING("Failed to load QWAVE.DLL for using diffserv on outgoing IP packets\n");
goto err_lock;
}
WaitForSingleObject(qwaveDLLModuleLock, INFINITE);
if (qwaveDLLModuleHandle == NULL) {
if ((qwaveDLLModuleHandle = LoadLibrary("QWAVE.DLL")) == NULL) {
OS_WARNING("os_sockLoadQwaveLibrary", 0,
"Failed to load QWAVE.DLL for using diffserv on outgoing IP packets");
DDS_WARNING("Failed to load QWAVE.DLL for using diffserv on outgoing IP packets\n");
goto err_load_lib;
}
@ -264,8 +262,7 @@ os_sockLoadQwaveLibrary(void)
if ((qwaveQOSCreateHandleFunc == 0) || (qwaveQOSCloseHandleFunc == 0) ||
(qwaveQOSAddSocketToFlowFunc == 0) || (qwaveQOSSetFlowFunc == 0)) {
OS_WARNING("os_sockLoadQwaveLibrary", 0,
"Failed to resolve entry points for using diffserv on outgoing IP packets");
DDS_WARNING("Failed to resolve entry points for using diffserv on outgoing IP packets\n");
goto err_find_func;
}
}
@ -277,7 +274,6 @@ err_find_func:
err_load_lib:
ReleaseMutex(qwaveDLLModuleLock);
err_lock:
return os_resultFail;
}
@ -384,7 +380,7 @@ os_sockSetDscpValueWithQos(
char errmsg[1024];
errNo = os_getErrno();
(void)os_strerror_r(errNo, errmsg, sizeof errmsg);
OS_ERROR("os_sockSetDscpValue", 0, "QOSCreateHandle failed: %d %s", errNo, errmsg);
DDS_ERROR("QOSCreateHandle failed: %d %s\n", errNo, errmsg);
goto err_create_handle;
}
@ -397,7 +393,7 @@ os_sockSetDscpValueWithQos(
char errmsg[1024];
errNo = os_getErrno();
(void)os_strerror_r(errNo, errmsg, sizeof errmsg);
OS_ERROR("os_sockSetDscpValue", 0, "QOSAddSocketToFlow failed: %d %s", errNo, errmsg);
DDS_ERROR("QOSAddSocketToFlow failed: %d %s\n", errNo, errmsg);
qwaveQOSCloseHandleFunc(qosHandle);
goto err_add_flow;
}
@ -405,9 +401,8 @@ os_sockSetDscpValueWithQos(
if (value != defaultDscp) {
if (!setDscpSupported) {
OS_WARNING("os_sockSetDscpValue", 0,
"Failed to set diffserv value to %lu value used is %d, not supported on this platform",
value, defaultDscp);
DDS_WARNING("Failed to set diffserv value to %lu value used is %d, not supported on this platform\n",
value, defaultDscp);
goto err_set_flow;
}
@ -417,14 +412,13 @@ os_sockSetDscpValueWithQos(
if (!qosResult) {
errNo = os_getErrno();
if ((errNo == ERROR_ACCESS_DENIED) || (errNo == ERROR_ACCESS_DISABLED_BY_POLICY)) {
OS_WARNING("os_sockSetDscpValue", 0,
"Failed to set diffserv value to %lu value used is %d, not enough privileges",
value, defaultDscp);
DDS_WARNING("Failed to set diffserv value to %lu value used is %d, not enough privileges\n",
value, defaultDscp);
} else {
char errmsg[1024];
errNo = os_getErrno();
(void)os_strerror_r(errNo, errmsg, sizeof errmsg);
OS_ERROR("os_sockSetDscpValue", 0, "QOSSetFlow failed: %d %s", errNo, errmsg);
DDS_ERROR("QOSSetFlow failed: %d %s\n", errNo, errmsg);
}
goto err_set_flow;
}
@ -435,7 +429,6 @@ os_sockSetDscpValueWithQos(
err_set_flow:
err_add_flow:
err_create_handle:
return result;
}
@ -447,11 +440,11 @@ os_sockSetDscpValue(
{
os_result result;
if (IsWindowsVistaOrGreater() && (os_sockLoadQwaveLibrary() == os_resultSuccess)) {
result = os_sockSetDscpValueWithQos(sock, value, IsWindows7OrGreater());
} else {
result = os_sockSetDscpValueWithTos(sock, value);
}
if (IsWindowsVistaOrGreater() && (os_sockLoadQwaveLibrary() == os_resultSuccess)) {
result = os_sockSetDscpValueWithQos(sock, value, IsWindows7OrGreater());
} else {
result = os_sockSetDscpValueWithTos(sock, value);
}
return result;
}
@ -516,7 +509,7 @@ os_sockSetNonBlocking(
r = os_resultInvalid;
break;
case WSANOTINITIALISED:
OS_FATAL("os_sockSetNonBlocking", 0, "Socket-module not initialised; ensure os_socketModuleInit is performed before using the socket module.");
DDS_FATAL("Socket-module not initialised; ensure os_socketModuleInit is performed before using the socket module\n");
default:
r = os_resultFail;
break;

View file

@ -26,32 +26,6 @@
#include "../snippets/code/os_stdlib_strcasecmp.c"
#include "../snippets/code/os_stdlib_strncasecmp.c"
static int32_t
os__ensurePathExists(
_In_z_ const char* dir_name);
/**
* \brief create a directory with default
* security descriptor. The mode parameter
* is ignored for this Operating System.
*
*/
int32_t
os_mkdir(
const char *path,
os_mode_t mode)
{
int32_t result = 0;
if (CreateDirectory(path, NULL)) {
result = 0;
}
else {
result = -1;
}
return result;
}
os_result
os_gethostname(
char *hostname,
@ -67,7 +41,7 @@ os_gethostname(
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
OS_FATAL("os_gethostname", 0, "WSAStartup failed, no compatible socket implementation available");
DDS_FATAL("WSAStartup failed, no compatible socket implementation available\n");
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
return os_resultFail;
@ -114,38 +88,6 @@ os_putenv(
return result;
}
const char *
os_fileSep(void)
{
return "\\";
}
const char *
os_pathSep(void)
{
return ";";
}
os_result
os_access(
const char *file_path,
int32_t permission)
{
struct _stat statbuf;
os_result result;
result = os_resultFail;
if (file_path) {
if (_stat(file_path, &statbuf) == 0) {
if ((statbuf.st_mode & permission) == permission) {
result = os_resultSuccess;
}
}
}
return result;
}
#pragma warning( disable : 4996 )
int
os_vfprintfnosigpipe(
@ -156,184 +98,6 @@ os_vfprintfnosigpipe(
return vfprintf(file, format, args);
}
os_result
os_stat(
const char *path,
struct os_stat *buf)
{
os_result result;
struct _stat32 _buf;
int r;
r = _stat32(path, &_buf);
if (r == 0) {
buf->stat_mode = _buf.st_mode;
buf->stat_size = _buf.st_size;
buf->stat_mtime.tv_sec = _buf.st_mtime;
buf->stat_mtime.tv_nsec = 0;
result = os_resultSuccess;
}
else {
result = os_resultFail;
}
return result;
}
os_result os_remove(const char *pathname)
{
return (remove(pathname) == 0) ? os_resultSuccess : os_resultFail;
}
os_result os_rename(const char *oldpath, const char *newpath)
{
(void)os_remove(newpath);
return (rename(oldpath, newpath) == 0) ? os_resultSuccess : os_resultFail;
}
/* The result of os_fileNormalize should be freed with os_free */
_Ret_z_
_Must_inspect_result_
char *
os_fileNormalize(
_In_z_ const char *filepath)
{
char *norm;
const char *fpPtr;
char *normPtr;
norm = os_malloc(strlen(filepath) + 1);
fpPtr = filepath;
normPtr = norm;
while (*fpPtr != '\0') {
*normPtr = *fpPtr;
if ((*fpPtr == '/') || (*fpPtr == '\\')) {
*normPtr = OS_FILESEPCHAR;
normPtr++;
} else {
if (*fpPtr != '\"') {
normPtr++;
}
}
fpPtr++;
}
*normPtr = '\0';
return norm;
}
os_result
os_fsync(
FILE *fHandle)
{
os_result r;
if (FlushFileBuffers((HANDLE)fHandle)) {
r = os_resultSuccess;
}
else {
r = os_resultFail;
}
return r;
}
_Ret_opt_z_ const char *
os_getTempDir(void)
{
const char * dir_name = NULL;
dir_name = os_getenv("OSPL_TEMP");
/* if OSPL_TEMP is not defined use the TEMP variable */
if (dir_name == NULL || (strcmp(dir_name, "") == 0)) {
dir_name = os_getenv("TEMP");
}
/* if TEMP is not defined use the TMP variable */
if (dir_name == NULL || (strcmp(dir_name, "") == 0)) {
dir_name = os_getenv("TMP");
}
/* Now we need to verify if we found a temp directory path, and if we did
* we have to make sure all the (sub)directories in the path exist.
* This is needed to prevent any other operations from using the directory
* path while it doesn't exist and therefore running into errors.
*/
if (dir_name == NULL || (strcmp(dir_name, "") == 0)) {
OS_ERROR("os_getTempDir", 0,
"Could not retrieve temporary directory path - "
"neither of environment variables TEMP, TMP, OSPL_TEMP were set");
}
else if (os__ensurePathExists(dir_name) != 0)
{
OS_ERROR("os_getTempDir", 0,
"Could not ensure all (sub)directories of the temporary directory\n"
"path '%s' exist.\n"
"This has consequences for the ability of OpenSpliceDDS to run\n"
"properly, as the directory path must be accessible to create\n"
"database and key files in. Without this ability OpenSpliceDDS can\n"
"not start.\n",
dir_name);
}
return dir_name;
}
int32_t
os__ensurePathExists(
_In_z_ const char* dir_name)
{
char* tmp;
char* ptr;
char ptrTmp;
struct os_stat statBuf;
os_result status;
int32_t result = 0;
int32_t cont = 1;
tmp = os_strdup(dir_name);
for (ptr = tmp; cont; ptr++)
{
if (*ptr == '\\' || *ptr == '/' || *ptr == '\0')
{
ptrTmp = ptr[0];
ptr[0] = '\0';
status = os_stat(tmp, &statBuf);
if (status != os_resultSuccess)
{
os_mkdir(tmp, 0);
status = os_stat(tmp, &statBuf);
}
if (!OS_ISDIR(statBuf.stat_mode))
{
if ((strlen(tmp) == 2) && (tmp[1] == ':')) {
/*This is a device like for instance: 'C:'*/
}
else
{
OS_ERROR("os_ensurePathExists", 0,
"Unable to create directory '%s' within path '%s'. Errorcode: %d",
tmp,
dir_name,
os_getErrno());
result = -1;
}
}
ptr[0] = ptrTmp;
}
if (*ptr == '\0' || result == -1)
{
cont = 0;
}
}
os_free(tmp);
return result;
}
#pragma warning( disable : 4996 )
int
os_vsnprintf(
@ -404,16 +168,6 @@ ssize_t os_write(
return _write(fd, buf, (unsigned int)count); /* Type casting is done for the warning of conversion from 'size_t' to 'unsigned int', which may cause possible loss of data */
}
void os_flockfile(FILE *file)
{
_lock_file (file);
}
void os_funlockfile(FILE *file)
{
_unlock_file (file);
}
int os_getopt(
_In_range_(0, INT_MAX) int argc,
_In_reads_z_(argc) char **argv,

View file

@ -188,8 +188,6 @@ os_startRoutineWrapper(
/* Call the user routine */
resultValue = context->startRoutine(context->arguments);
os_report_stack_free();
/* Free the thread context resources, arguments is responsibility */
/* for the caller of os_threadCreate */
os_free (context->threadName);
@ -236,7 +234,7 @@ os_threadCreate(
(LPVOID)threadContext,
(DWORD)0, &threadIdent);
if (threadHandle == 0) {
OS_WARNING("os_threadCreate", os_getErrno(), "Failed with System Error Code: %i\n", os_getErrno ());
DDS_WARNING("Failed with System Error Code: %i\n", os_getErrno ());
return os_resultFail;
}
@ -277,7 +275,7 @@ os_threadCreate(
}
}
if (SetThreadPriority (threadHandle, effective_priority) == 0) {
OS_INFO("os_threadCreate", os_getErrno(), "SetThreadPriority failed with %i", os_getErrno());
DDS_INFO("SetThreadPriority failed with %i\n", os_getErrno());
}
/* ES: dds2086: Close handle should not be performed here. Instead the handle
@ -358,29 +356,6 @@ os_threadWaitExit(
return os_resultSuccess;
}
/** \brief Figure out the identity of the current thread
*
* Possible Results:
* - returns the actual length of threadIdentity
*/
int
os_threadFigureIdentity(
char *threadIdentity,
uint32_t threadIdentitySize)
{
int size;
char* threadName;
threadName = (char *)os_threadMemGet(OS_THREAD_NAME);
if (threadName != NULL) {
size = snprintf (threadIdentity, threadIdentitySize, "%s 0x%"PRIx32, threadName, GetCurrentThreadId());
} else {
size = snprintf (threadIdentity, threadIdentitySize, "0x%"PRIx32, GetCurrentThreadId());
}
return size;
}
int
os_threadGetThreadName(
char *buffer,

View file

@ -19,7 +19,6 @@ set(sources
"iter.c"
"mutex.c"
"once.c"
"report.c"
"rwlock.c"
"stdlib.c"
"strtoll.c"

View file

@ -1,404 +0,0 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "CUnit/Test.h"
#include "os/os.h"
#include "os/os_project.h"
#include <stdio.h>
CU_Init(os_report)
{
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_ERRORFILE=vdds_test_error");
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_INFOFILE=vdds_test_info");
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_LOGAPPEND=TRUE");
return 0;
}
void remove_logs()
{
const char * error_file_name = os_getenv(OS_PROJECT_NAME_NOSPACE_CAPS"_ERRORFILE");
const char * info_file_name = os_getenv(OS_PROJECT_NAME_NOSPACE_CAPS"_INFOFILE");
os_remove(error_file_name);
os_remove(info_file_name);
}
void check_existence(os_result error_log_existence, os_result info_log_existence)
{
const char * error_file_name = os_getenv(OS_PROJECT_NAME_NOSPACE_CAPS"_ERRORFILE");
const char * info_file_name = os_getenv(OS_PROJECT_NAME_NOSPACE_CAPS"_INFOFILE");
CU_ASSERT(os_access(error_file_name, OS_ROK) == error_log_existence);
CU_ASSERT(os_access(info_file_name, OS_ROK) == info_log_existence);
}
CU_Clean(os_report)
{
remove_logs();
return 0;
}
CU_Test(os_report, re_init)
{
os_reportInit(true);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultSuccess);
os_reportExit();
os_reportInit(true);
check_existence(os_resultSuccess, os_resultSuccess);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
os_reportExit();
remove_logs();
}
CU_Test(os_report, stack_critical)
{
os_reportInit(true);
OS_REPORT_STACK();
OS_CRITICAL(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
check_existence(os_resultFail, os_resultFail);
OS_REPORT_FLUSH(false);
// Since a critical is logged, the error log should be created
check_existence(os_resultSuccess, os_resultFail);
os_reportExit();
remove_logs();
}
CU_Test(os_report, stack_non_critical)
{
os_reportInit(true);
OS_REPORT_STACK();
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
check_existence(os_resultFail, os_resultFail);
OS_REPORT_FLUSH(false);
// Since a non critical is logged, the error log should not be created
check_existence(os_resultFail, os_resultFail);
os_reportExit();
remove_logs();
}
CU_Test(os_report, error_file_creation_critical)
{
os_reportInit(true);
OS_CRITICAL(OS_FUNCTION, 0, "os_report-critical-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultFail);
os_reportExit();
remove_logs();
}
CU_Test(os_report, error_file_creation_fatal)
{
os_reportInit(true);
OS_FATAL(OS_FUNCTION, 0, "os_report-fatal-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultFail);
os_reportExit();
remove_logs();
}
CU_Test(os_report, info_file_creation_warning)
{
os_reportInit(true);
OS_WARNING(OS_FUNCTION, 0, "os_report-warning-test %d", __LINE__);
check_existence(os_resultFail, os_resultSuccess);
os_reportExit();
remove_logs();
}
CU_Test(os_report, info_file_creation_info)
{
os_reportInit(true);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultFail, os_resultSuccess);
os_reportExit();
remove_logs();
}
CU_Test(os_report, verbosity_low)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
os_reportVerbosity = OS_REPORT_ERROR;
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultFail, os_resultFail);
os_reportExit();
remove_logs();
}
CU_Test(os_report, verbosity_high)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
os_reportVerbosity = OS_REPORT_DEBUG;
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultFail, os_resultSuccess);
os_reportExit();
remove_logs();
}
CU_Test(os_report, verbosity_equal)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
os_reportVerbosity = OS_REPORT_WARNING;
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultFail, os_resultSuccess);
os_reportExit();
remove_logs();
}
CU_Test(os_report, stack_verbosity_low)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
os_reportVerbosity = OS_REPORT_ERROR;
OS_REPORT_STACK();
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
OS_REPORT_FLUSH(true);
check_existence(os_resultFail, os_resultFail);
os_reportExit();
remove_logs();
}
CU_Test(os_report, stack_verbosity_high)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
os_reportVerbosity = OS_REPORT_DEBUG;
OS_REPORT_STACK();
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
OS_REPORT_FLUSH(true);
check_existence(os_resultFail, os_resultSuccess);
os_reportExit();
remove_logs();
}
CU_Test(os_report, stack_verbosity_equal)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
os_reportVerbosity = OS_REPORT_WARNING;
OS_REPORT_STACK();
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
OS_REPORT_FLUSH(true);
check_existence(os_resultFail, os_resultSuccess);
os_reportExit();
remove_logs();
}
CU_Test(os_report, no_log_append)
{
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultSuccess);
os_reportExit();
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_LOGAPPEND=FALSE");
os_reportInit(true);
// Both logs should be deleted
check_existence(os_resultFail, os_resultFail);
os_reportExit();
remove_logs();
}
CU_Test(os_report, log_dir)
{
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_LOGPATH=.");
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultSuccess);
os_reportExit();
remove_logs();
}
CU_Test(os_report, verbosity_env_value_info)
{
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=0");
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultSuccess);
os_reportExit();
remove_logs();
//reset for other tests.
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=");
}
CU_Test(os_report, verbosity_env_value_error)
{
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=3");
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultFail);
os_reportExit();
remove_logs();
//reset for other tests.
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=");
}
CU_Test(os_report, verbosity_env_value_error_as_string)
{
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=ERROR");
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
OS_DEBUG(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultFail);
os_reportExit();
remove_logs();
//reset for other tests.
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=");
}
CU_Test(os_report, verbosity_wrong_env_value)
{
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=WRONG");
os_reportInit(true);
check_existence(os_resultFail, os_resultFail);
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
OS_DEBUG(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
check_existence(os_resultSuccess, os_resultFail);
os_reportExit();
remove_logs();
//reset for other tests.
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=");
}

View file

@ -12,261 +12,8 @@
#include "CUnit/Test.h"
#include "os/os.h"
#ifndef WINCE
#include <fcntl.h>
#endif
#if (defined WIN32 || defined WIN64)
#include <direct.h>
#include <Windows.h>
#endif
static const os_time wait_time_out = { 1, 0 };
static FILE *file;
#define ENABLE_TRACING 0
#define FLOCKFILE_THREAD1_INPUT1 "thread1_flockfile_proc: *** input 1 ***"
#define FLOCKFILE_THREAD1_INPUT3 "thread1_flockfile_proc: *** input 3 ***"
#define FLOCKFILE_THREAD2_INPUT2 "thread2_flockfile_proc: *** input 2 ***"
#define defSignal(signal) \
static os_cond signal;\
static bool signal##_set = false;
#define initSignal(signal, mutex) \
os_condInit(&signal, &mutex);\
signal##_set = false;
#define sendSignal(signal, mutex) \
os_mutexLock(&mutex);\
/* signaling */ \
signal##_set = true; \
os_condSignal(&signal);\
os_mutexUnlock(&mutex);
#define waitForSignal(signal, mutex) \
os_mutexLock(&mutex);\
while(!signal##_set) { \
/* waiting for signal */ \
os_condWait(&signal, &mutex);\
/* received */ \
} /* else already signal received */ \
os_mutexUnlock(&mutex);
#define timedWaitSignal(signal, mutex, time) \
{ \
os_time duration = time; \
os_time startTime, currentTime; \
os_result rc; \
os_mutexLock(&mutex); \
startTime = os_timeGetElapsed(); \
while(!signal##_set) { \
/* waiting for signal */ \
rc = os_condTimedWait(&signal, &mutex, &duration); \
/* signal received or timeout */ \
if(rc == os_resultTimeout) { \
break; \
} else { \
currentTime = os_timeGetElapsed(); \
if(os_timeCompare(os_timeSub(currentTime, startTime), wait_time_out) >= 0) { \
break; \
} \
duration = os_timeSub(wait_time_out, os_timeSub(currentTime, startTime)); \
} \
} /* else already signal received */ \
os_mutexUnlock(&mutex);\
}
static os_mutex mutex;
static bool do_locking;
/* signals set by threads */
defSignal(thread1_started);
defSignal(thread2_started);
defSignal(action1_done);
defSignal(action2_done);
/* signals set by the test orchestrator (doFlockfileTest) */
defSignal(do_action1);
defSignal(do_action2);
defSignal(do_action3);
static uint32_t thread1_flockfile_proc(void* args) {
int result = 0;
(void)args;
/* thread1: start */
sendSignal(thread1_started, mutex);
waitForSignal(do_action1, mutex);
if(do_locking) os_flockfile(file);
/* Thread1: writing input 1 to the file */
result = fputs(FLOCKFILE_THREAD1_INPUT1, file);
CU_ASSERT(result >= 0);
sendSignal(action1_done, mutex);
waitForSignal(do_action3, mutex);
/* Thread1: writing input 3 to the file */
result = fputs(FLOCKFILE_THREAD1_INPUT3, file);
CU_ASSERT(result >= 0);
if(do_locking) os_funlockfile(file);
/* thread1: end */
return 0;
}
static uint32_t thread2_flockfile_proc(void* args) {
int result = 0;
(void)args;
/* thread2: start */
sendSignal(thread2_started, mutex);
waitForSignal(do_action2, mutex);
/* Thread2: writing input 2 to the file */
result = fputs(FLOCKFILE_THREAD2_INPUT2, file);
CU_ASSERT(result >= 0);
sendSignal(action2_done, mutex);
/* thread2: end */
return 0;
}
bool doFlockfileTest(bool lock) {
bool testPassed = true;
bool strcmpResult = true;
os_result result;
os_threadAttr threadAttr;
os_threadId thread1;
os_threadId thread2;
int FLOCKFILE_INPUT_MAX = sizeof(FLOCKFILE_THREAD1_INPUT1);
do_locking = lock;
char *buffer = os_malloc(sizeof(char) * (unsigned)FLOCKFILE_INPUT_MAX);
file = tmpfile();
os_mutexInit(&mutex);
/* initialize all signal conditions */
os_mutexLock(&mutex);
initSignal(thread1_started, mutex);
initSignal(thread2_started, mutex);
initSignal(action1_done, mutex);
initSignal(action2_done, mutex);
initSignal(do_action1, mutex);
initSignal(do_action2, mutex);
initSignal(do_action3, mutex);
os_mutexUnlock(&mutex);
/* create threads... */
os_threadAttrInit(&threadAttr);
result = os_threadCreate(
&thread1,
"thread 1",
&threadAttr,
thread1_flockfile_proc,
NULL);
CU_ASSERT(result == os_resultSuccess);
result = os_threadCreate(
&thread2,
"thread 2",
&threadAttr,
thread2_flockfile_proc,
NULL);
CU_ASSERT(result == os_resultSuccess);
/* wait for threads to start */
waitForSignal(thread1_started, mutex);
waitForSignal(thread2_started, mutex);
/* get thread one to do its first thing */
sendSignal(do_action1, mutex);
/* wait for thread 1 to acknowledge */
timedWaitSignal(action1_done, mutex, wait_time_out);
/* kick thead 2 */
sendSignal(do_action2, mutex);
/* wait for thread 2 to acknowledge */
timedWaitSignal(action2_done, mutex, wait_time_out);
/* kick thread 1, again */
sendSignal(do_action3, mutex);
/* wait for threads to shutdown */
result = os_threadWaitExit(thread1,NULL);
CU_ASSERT(result == os_resultSuccess);
result = os_threadWaitExit(thread2,NULL);
CU_ASSERT(result == os_resultSuccess);
/* if lock then Expected action order: 1 3 2
* else Expected action order: 1 2 3 */
rewind(file);
if(lock) {
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > (char*)0) {
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD1_INPUT1) == 0);
CU_ASSERT(strcmpResult);
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
}
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > (char*)0) {
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD1_INPUT3) == 0);
CU_ASSERT(strcmpResult);
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
}
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > (char*)0) {
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD2_INPUT2) == 0);
CU_ASSERT(strcmpResult);
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
}
} else {
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > (char*)0) {
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD1_INPUT1) == 0);
CU_ASSERT(strcmpResult);
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
}
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > (char*)0) {
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD2_INPUT2) == 0);
CU_ASSERT(strcmpResult);
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
}
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > (char*)0) {
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD1_INPUT3) == 0);
CU_ASSERT(strcmpResult);
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
}
}
/* cleanup */
os_free(buffer);
fclose(file);
os_mutexLock(&mutex);
os_condDestroy(&do_action1);
os_condDestroy(&do_action2);
os_condDestroy(&do_action3);
os_condDestroy(&thread1_started);
os_condDestroy(&thread2_started);
os_condDestroy(&action1_done);
os_condDestroy(&action2_done);
os_mutexUnlock(&mutex);
os_mutexDestroy(&mutex);
/* doFlockfileTest */
return testPassed;
}
static int
vsnprintfTest(
const char *format,
@ -292,15 +39,8 @@ CU_Init(os_stdlib)
CU_Clean(os_stdlib)
{
/* Remove files used to test permissions */
remove ("exec_only");
remove ("read_exec");
remove ("read_only");
remove ("read_write_exec");
remove ("write_only");
remove ("existing_file");
os_osExit();
return 0;
os_osExit();
return 0;
}
CU_Test(os_stdlib, gethostname)
@ -356,254 +96,6 @@ CU_Test(os_stdlib, getenv)
printf ("Ending os_stdlib_getenv\n");
}
CU_Test(os_stdlib, fileSep)
{
#if defined WIN32
const char *wanted= "\\";
#else
const char *wanted= "/";
#endif
printf ("Starting os_stdlib_fileSep_001\n");
CU_ASSERT (strcmp(os_fileSep(), wanted) == 0);
printf ("Ending os_stdlib_fileSep\n");
}
CU_Test(os_stdlib, access)
{
os_result os_res;
os_result wanted;
int fh;
/* Check correct functioning of os_access, non existing file read access */
printf ("Starting os_stdlib_access_001\n");
#if defined VXWORKS_RTP || defined _WRS_KERNEL
printf ("N.A - Not tested for vxworks.\n");
#else
os_res = os_access("non_existing_file", OS_ROK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access, non existing file write access */
printf ("Starting os_stdlib_access_002\n");
os_res = os_access("non_existing_file", OS_WOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access, non existing file execute access */
printf ("Starting os_stdlib_access_003\n");
os_res = os_access("non_existing_file", OS_XOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access, non existing file existence */
printf ("Starting os_stdlib_access_004\n");
os_res = os_access("non_existing_file", OS_FOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access, existing file with no
permissions read access */
printf ("Starting os_stdlib_access_005\n");
#ifdef WIN32
fh= _creat("existing_file", 0000); /* Note always has read & execute */
if (fh != -1)
_close(fh);
wanted = os_resultSuccess;
#else
fh= creat("existing_file", 0000);
if (fh != -1)
close(fh);
wanted = os_resultFail;
#endif /* WIN32 */
os_res = os_access("existing_file", OS_ROK);
CU_ASSERT (os_res == wanted);
/* Check correct functioning of os_access, existing file with no
permissions write access */
printf ("Starting os_stdlib_access_006\n");
os_res = os_access("existing_file", OS_WOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access, existing file with no
permissions execute access */
printf ("Starting os_stdlib_access_007\n");
os_res = os_access("existing_file", OS_XOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access, existing file with no permissions existence */
printf ("Starting os_stdlib_access_008\n");
os_res = os_access("existing_file", OS_FOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read permissions read access */
printf ("Starting os_stdlib_access_009\n");
#ifdef WIN32
fh= _creat("read_only", _S_IREAD); /* Note always has read & execute */
if (fh != -1)
_close(fh);
#else
fh= creat("read_only", S_IRUSR);
if (fh != -1)
close(fh);
#endif /* WIN32 */
os_res = os_access("read_only", OS_ROK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read permissions write access */
printf ("Starting os_stdlib_access_010\n");
os_res = os_access("read_only", OS_WOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access,
existing file with read permissions execute access */
printf ("Starting os_stdlib_access_011\n");
os_res = os_access("read_only", OS_XOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access,
existing file with read permissions existence */
printf ("Starting os_stdlib_access_012\n");
os_res = os_access("read_only", OS_FOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with write permissions read access */
printf ("Starting os_stdlib_access_013\n");
#ifdef WIN32
fh= _creat("write_only", _S_IWRITE); /* Note windows automatically has read access can't have write only */
if (fh != -1)
_close(fh);
wanted = os_resultSuccess;
#else
fh= creat("write_only", S_IWUSR);
if (fh != -1)
close(fh);
wanted = os_resultFail;
#endif /* WIN32 */
os_res = os_access("write_only", OS_ROK);
CU_ASSERT (os_res == wanted);
/* Check correct functioning of os_access,
existing file with write permissions write access */
printf ("Starting os_stdlib_access_014\n");
os_res = os_access("write_only", OS_WOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with write permissions execute access */
printf ("Starting os_stdlib_access_015\n");
os_res = os_access("write_only", OS_XOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access,
existing file with write permissions existence */
printf ("Starting os_stdlib_access_016\n");
os_res = os_access("write_only", OS_FOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with exec permissions read access */
printf ("Starting os_stdlib_access_017\n");
#ifdef WIN32
fh= _creat("exec_only" OS_OS_EXESUFFIX, _S_IREAD); /* Windows always has read and can't do execute (that's based upon filename ext only) */
if (fh != -1)
_close(fh);
wanted = os_resultSuccess;
#else
fh= creat("exec_only" OS_OS_EXESUFFIX, S_IXUSR);
if (fh != -1)
close(fh);
wanted = os_resultFail;
#endif /* WIN32 */
os_res = os_access("exec_only" OS_OS_EXESUFFIX, OS_ROK);
CU_ASSERT (os_res == wanted);
/* Check correct functioning of os_access,
existing file with exec permissions write access */
printf ("Starting os_stdlib_access_018\n");
os_res = os_access("exec_only" OS_OS_EXESUFFIX, OS_WOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access,
existing file with exec permissions execute access */
printf ("Starting os_stdlib_access_019\n");
os_res = os_access("exec_only" OS_OS_EXESUFFIX, OS_XOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with exec permissions existence */
printf ("Starting os_stdlib_access_020\n");
os_res = os_access("exec_only" OS_OS_EXESUFFIX, OS_FOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read/write/exec permissions read access */
printf ("Starting os_stdlib_access_021\n");
#ifdef WIN32
fh= _creat("read_write_exec" OS_OS_EXESUFFIX, _S_IREAD | _S_IWRITE); /* Windows always has read and can't do execute (that's based upon filename ext only) */
if (fh != -1)
_close(fh);
#else
fh= creat("read_write_exec" OS_OS_EXESUFFIX, S_IRUSR | S_IWUSR | S_IXUSR);
if (fh != -1)
close(fh);
#endif /* WIN32 */
os_res = os_access("read_write_exec" OS_OS_EXESUFFIX, OS_ROK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read/write/exec permissions write access */
printf ("Starting os_stdlib_access_022\n");
os_res = os_access("read_write_exec" OS_OS_EXESUFFIX, OS_WOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read/write/exec permissions execute access */
printf ("Starting os_stdlib_access_023\n");
os_res = os_access("read_write_exec" OS_OS_EXESUFFIX, OS_XOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read/write/exec permissions existence */
printf ("Starting os_stdlib_access_024\n");
os_res = os_access("read_write_exec" OS_OS_EXESUFFIX, OS_FOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read/exec permissions read+write access */
printf ("Starting os_stdlib_access_025\n");
#ifdef WIN32
fh= _creat("read_exec" OS_OS_EXESUFFIX, _S_IREAD); /* Windows always has read and can't do execute (that's based upon filename ext only) */
if (fh != -1)
_close(fh);
#else
fh= creat("read_exec" OS_OS_EXESUFFIX, S_IRUSR | S_IXUSR);
if (fh != -1)
close(fh);
#endif /* WIN32 */
os_res = os_access("read_exec" OS_OS_EXESUFFIX, OS_ROK|OS_WOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access,
existing file with read/exec permissions write+exec access */
printf ("Starting os_stdlib_access_026\n");
os_res = os_access("read_exec" OS_OS_EXESUFFIX, OS_WOK|OS_XOK);
CU_ASSERT (os_res == os_resultFail);
/* Check correct functioning of os_access,
existing file with read/exec permissions read+exec access */
printf ("Starting os_stdlib_access_027\n");
os_res = os_access("read_exec" OS_OS_EXESUFFIX, OS_ROK|OS_XOK);
CU_ASSERT (os_res == os_resultSuccess);
/* Check correct functioning of os_access,
existing file with read/exec permissions read+exec+existence */
printf ("Starting os_stdlib_access_028\n");
os_res = os_access("read_exec" OS_OS_EXESUFFIX, OS_ROK|OS_XOK|OS_FOK);
CU_ASSERT (os_res == os_resultSuccess);
#endif /* VXWORKS */
printf ("Ending stdlib_os_access\n");
}
CU_Test(os_stdlib, vsnprintf)
{
printf ("Starting os_stdlib_vsnprintf_001\n");
@ -694,27 +186,6 @@ CU_Test(os_stdlib, index)
printf ("Ending os_stdlib_index\n");
}
CU_Test(os_stdlib, flockfile)
{
bool result = false;
os_osInit();
/* Check writing in a FILE from multiple threads without using os_flockfile. */
printf ("Starting os_stdlib_flockfile_001\n");
result = doFlockfileTest(false);
CU_ASSERT (result);
/* Check writing in a FILE from multiple threads using os_flockfile in the first thread. */
printf ("Starting os_stdlib_flockfile_002\n");
result = doFlockfileTest(true);
CU_ASSERT (result);
printf ("Ending os_stdlib_flockfile\n");
os_osExit();
}
CU_Test(os_stdlib, getopt)
{
int c = 0;