replaced strerror() with thread-safe strerror_malloc()

This commit is contained in:
Timerix 2025-11-21 13:15:17 +05:00
parent 225a48a8d9
commit 0b4574b53e
8 changed files with 62 additions and 22 deletions

View File

@ -20,7 +20,7 @@ typedef struct Array_ {
static inline Array_ Array_alloc_size(u32 size){ static inline Array_ Array_alloc_size(u32 size){
if(size == 0) if(size == 0)
return Array_null; return Array_null;
return Array_construct_size(size > 0 ? malloc(size) : NULL, size); return Array_construct_size(malloc(size), size);
} }
#define Array_realloc(SELF, T, COUNT) Array_realloc_size(SELF, (COUNT) * sizeof(T)) #define Array_realloc(SELF, T, COUNT) Array_realloc_size(SELF, (COUNT) * sizeof(T))

View File

@ -74,8 +74,9 @@ typedef struct Result_ {
RESULT_ERROR_CODE(NONE, 0, MSG, IS_MSG_ON_HEAP); RESULT_ERROR_CODE(NONE, 0, MSG, IS_MSG_ON_HEAP);
#define RESULT_ERROR_FMT(FORMAT, ARGS...) \ #define RESULT_ERROR_FMT(FORMAT, ARGS...) \
RESULT_ERROR_CODE_FMT(NONE, 0, FORMAT ,##ARGS) RESULT_ERROR_CODE_FMT(NONE, 0, FORMAT ,##ARGS)
#define RESULT_ERROR_ERRNO() \ #define RESULT_ERROR_ERRNO() \
RESULT_ERROR_CODE(LIBC_ERRNO, errno, strerror(errno), false) RESULT_ERROR_CODE(LIBC_ERRNO, errno, strerror_malloc(errno), true)
#define RESULT_VOID (Result_){ .error = NULL, .u = 0 } #define RESULT_VOID (Result_){ .error = NULL, .u = 0 }
#define RESULT_VALUE(FIELD, V) (Result_){ .error = NULL, .FIELD = V } #define RESULT_VALUE(FIELD, V) (Result_){ .error = NULL, .FIELD = V }
@ -122,7 +123,7 @@ typedef struct Result_ {
#define try_stderrcode(CALL) do {\ #define try_stderrcode(CALL) do {\
int r = CALL;\ int r = CALL;\
if(r != 0){\ if(r != 0){\
Return RESULT_ERROR_CODE(LIBC_ERRNO, r, strerror(r), false);\ Return RESULT_ERROR_CODE(LIBC_ERRNO, r, strerror_malloc(r), true);\
}\ }\
} while(0) } while(0)

View File

@ -9,3 +9,6 @@ char* _vstrcat_malloc(u64 n, cstr str0, va_list args);
char* sprintf_malloc(cstr format, ...) ATTRIBUTE_CHECK_FORMAT_PRINTF(1, 2); char* sprintf_malloc(cstr format, ...) ATTRIBUTE_CHECK_FORMAT_PRINTF(1, 2);
char* vsprintf_malloc(cstr format, va_list args); char* vsprintf_malloc(cstr format, va_list args);
/// thread-safe version of strerror
char* strerror_malloc(int errcode);

View File

@ -50,7 +50,7 @@ str Error_toStr(Error* e){
void Error_printAndExit(Error* e){ void Error_printAndExit(Error* e){
str e_str = Error_toStr(e); str e_str = Error_toStr(e);
printfe("%s\n", e_str.data); printfe("\n"FMT_str"\n", e_str.size, e_str.data);
free(e_str.data); free(e_str.data);
Error_free(e); Error_free(e);
exit(111); exit(111);

View File

@ -37,7 +37,12 @@ Result(bool) dir_create(cstr path){
if(mkdir(path, 0777) == -1) if(mkdir(path, 0777) == -1)
#endif #endif
{ {
Return RESULT_ERROR_FMT("Can't create dicectory '%s': %s", path, strerror(errno)); char* errno_s = strerror_malloc(errno);
ResultVar(void) err = RESULT_ERROR_FMT(
"Can't create dicectory '%s': %s",
path, errno_s);
free(errno_s);
Return err;
} }
Return RESULT_VALUE(i, true); Return RESULT_VALUE(i, true);

View File

@ -25,21 +25,29 @@ bool file_exists(cstr path){
Result(FILE*) file_open(cstr file_name, cstr fopen_mode){ Result(FILE*) file_open(cstr file_name, cstr fopen_mode){
FILE* f = fopen(file_name, fopen_mode); FILE* f = fopen(file_name, fopen_mode);
if(f == NULL){ if(f == NULL){
return RESULT_ERROR_FMT( char* errno_s = strerror_malloc(errno);
ResultVar(void) err = RESULT_ERROR_FMT(
"Can't open (%s) file '%s': %s", "Can't open (%s) file '%s': %s",
fopen_mode, file_name, strerror(errno)); fopen_mode, file_name, errno_s);
free(errno_s);
return err;
} }
return RESULT_VALUE(p, f); return RESULT_VALUE(p, f);
} }
Result(FILE*) file_openOrCreateReadWrite(cstr file_name){ Result(FILE*) file_openOrCreateReadWrite(cstr file_name){
FILE* f = fopen(file_name, "rb+"); cstr fopen_mode = "rb+";
FILE* f = fopen(file_name, fopen_mode);
if(f == NULL){ if(f == NULL){
f = fopen(file_name, "wb+"); fopen_mode = "wb+";
f = fopen(file_name, fopen_mode);
if(f == NULL){ if(f == NULL){
return RESULT_ERROR_FMT( char* errno_s = strerror_malloc(errno);
"Can't create (%s) file: %s", ResultVar(void) err = RESULT_ERROR_FMT(
file_name, strerror(errno)); "Can't open (%s) file '%s': %s",
fopen_mode, file_name, errno_s);
free(errno_s);
return err;
} }
} }
return RESULT_VALUE(p, f); return RESULT_VALUE(p, f);
@ -57,9 +65,12 @@ Result(i64) file_tellPos(FILE* f){
Result(void) file_seek(FILE* f, i64 offset, SeekOrigin origin){ Result(void) file_seek(FILE* f, i64 offset, SeekOrigin origin){
if(IFWIN(_fseeki64, fseeko64)(f, offset, (int)origin) != 0){ if(IFWIN(_fseeki64, fseeko64)(f, offset, (int)origin) != 0){
return RESULT_ERROR_FMT( char* errno_s = strerror_malloc(errno);
ResultVar(void) err = RESULT_ERROR_FMT(
"Can't seek (offset: "FMT_i64", origin: %i) in file: %s", "Can't seek (offset: "FMT_i64", origin: %i) in file: %s",
offset, origin, strerror(errno)); offset, origin, errno_s);
free(errno_s);
return err;
} }
return RESULT_VOID; return RESULT_VOID;
} }

View File

@ -1,3 +1,9 @@
// Enable POSIX 2004 definitions.
// Required to use strerror_r in ISO C.
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#endif
#include "tlibc/string/cstr.h" #include "tlibc/string/cstr.h"
char* cstr_copy(cstr self){ char* cstr_copy(cstr self){
@ -70,3 +76,15 @@ char* vsprintf_malloc(cstr format, va_list args){
} }
return buf; return buf;
} }
#if defined(_WIN64) || defined(_WIN32)
#define portable_strerror_s(BUF, BUFSIZE, ERRCODE) strerror_s(BUF, BUFSIZE, ERRCODE)
#else
#define portable_strerror_s(BUF, BUFSIZE, ERRCODE) strerror_r(ERRCODE, BUF, BUFSIZE)
#endif
char* strerror_malloc(int errcode){
const int buf_size = 256;
char* buf = malloc(buf_size);
portable_strerror_s(buf, buf_size, errcode);
return buf;
}

View File

@ -1,10 +1,7 @@
// posix version definition to use clock_gettime // Enable POSIX 2004 definitions.
// Required to use clock_gettime, localtime_r, gmtime_r in ISO C.
#ifndef _XOPEN_SOURCE #ifndef _XOPEN_SOURCE
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600 #define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 500
#endif
#endif #endif
#include "tlibc/time.h" #include "tlibc/time.h"
@ -45,8 +42,13 @@ void sleepMsec(msec_t time){
sleepNsec(time * M); sleepNsec(time * M);
} }
#define portable_localtime_s(time_t_ptr, tm_ptr) IFWIN(localtime_s(tm_ptr, time_t_ptr), localtime_r(time_t_ptr, tm_ptr)) #if defined(_WIN64) || defined(_WIN32)
#define portable_gmtime_s(time_t_ptr, tm_ptr) IFWIN(gmtime_s(tm_ptr, time_t_ptr), gmtime_r(time_t_ptr, tm_ptr)) #define portable_localtime_s(time_t_ptr, tm_ptr) localtime_s(tm_ptr, time_t_ptr)
#define portable_gmtime_s(time_t_ptr, tm_ptr) gmtime_s(tm_ptr, time_t_ptr)
#else
#define portable_localtime_s(time_t_ptr, tm_ptr) localtime_r(time_t_ptr, tm_ptr)
#define portable_gmtime_s(time_t_ptr, tm_ptr) gmtime_r(time_t_ptr, tm_ptr)
#endif
void DateTime_get(DateTime* dt, bool utc_time){ void DateTime_get(DateTime* dt, bool utc_time){
time_t c_time = time(NULL); time_t c_time = time(NULL);