Logs: the error of opening a log returned, not passed in errno
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run

On Windows proxy.h makes errno WSAGetLastError(), which cannot be
assigned, so the Windows build failed, and the error of fopen() would
not have been read there either. A type's init returns the errno value
(the C library's, read with _get_errno() on Windows), and logget() gives
it to its caller.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Vladimir Dubrovin 2026-10-23 17:20:56 +03:00
parent 30e2e34dd6
commit a3c417c82a
6 changed files with 34 additions and 23 deletions

View File

@ -384,13 +384,14 @@ static int h_external(int argc, unsigned char ** argv){
static int h_log(int argc, unsigned char ** argv){
struct logger *lg;
ROTATION rotation = (argc > 2)? getrotate(*argv[2]) : NONE;
int err = 0;
/* the same log as before is not opened again */
lg = logget((argc > 1)? argv[1] : (unsigned char *)"", rotation);
lg = logget((argc > 1)? argv[1] : (unsigned char *)"", rotation, &err);
if(!lg){
fprintf(stderr, "Unable to open log %.*s: %s, line %d\n",
(int)logselen((argc > 1)? argv[1] : (unsigned char *)""),
(argc > 1)? (char *)argv[1] : "", strerror(errno), linenum);
(argc > 1)? (char *)argv[1] : "", strerror(err), linenum);
return 1;
}
if(conf->stacksize < lg->type->stacksize) conf->stacksize = lg->type->stacksize;

View File

@ -508,19 +508,29 @@ static int matchfile(const unsigned char *selector){
return 1;
}
/* errno of the C library: on Windows proxy.h makes errno the socket error */
#ifdef _WIN32
static int crterrno(void){
int e = 0;
_get_errno(&e);
return e;
}
#else
#define crterrno() (errno)
#endif
static int fileinit(struct logger *lg){
unsigned char *name;
FILE *fp;
int err;
FILE *fp = NULL;
int err = 0;
if(!(name = malloc(LOGNAMESIZE))) return 21;
if(!(name = malloc(LOGNAMESIZE))) return ENOMEM;
dologname(name, lg->selector, NULL, lg->rotation, lg->rotated);
errno = ENAMETOOLONG;
fp = *name? fopen((char *)name, "a") : NULL;
err = errno;
if(!*name) err = ENAMETOOLONG;
else if(!(fp = fopen((char *)name, "a")) && !(err = crterrno())) err = EIO;
free(name);
errno = err;
if(!fp) return 1;
if(err) return err;
lg->data = fp;
return 0;
}
@ -671,7 +681,7 @@ void loginit(void){
#ifndef _WIN32
_3proxy_mutex_init(&syslog_mutex);
/* kept for the life of the process, as every syslog logger is */
(void)logget((const unsigned char *)"@3proxy", NONE);
(void)logget((const unsigned char *)"@3proxy", NONE, NULL);
#endif
}
@ -701,9 +711,9 @@ static void logsetparams(struct logger *lg, const unsigned char *params){
}
/* The logger named so, opened if none is: held until logput(). NULL, with
errno set, if it cannot be opened. A logger found with other parameters
takes the new ones. */
struct logger *logget(const unsigned char *selector, ROTATION rotation){
the error in *errp (an errno value) unless it is NULL, if it cannot be
opened. A logger found with other parameters takes the new ones. */
struct logger *logget(const unsigned char *selector, ROTATION rotation, int *errp){
struct logger *lg;
const struct logtype *type;
const unsigned char *params;
@ -730,7 +740,7 @@ struct logger *logget(const unsigned char *selector, ROTATION rotation){
free(lg);
}
_3proxy_mutex_unlock(&log_mutex);
errno = ENOMEM;
if(errp) *errp = ENOMEM;
return NULL;
}
memcpy(lg->selector, selector, len);
@ -745,13 +755,12 @@ struct logger *logget(const unsigned char *selector, ROTATION rotation){
lg->failtime = lg->rotated;
}
else if(err){
err = errno;
_3proxy_mutex_unlock(&log_mutex);
_3proxy_mutex_destroy(&lg->mutex);
if(lg->params) free(lg->params);
free(lg->selector);
free(lg);
errno = err;
if(errp) *errp = err;
return NULL;
}
lg->refs = 1;

View File

@ -318,12 +318,13 @@ static int srvprepare(struct srvstart *s, int argc, char **argv){
case 'l':
{
struct logger *lg;
int err = 0;
/* the same log the log command, or another service,
opened is shared with it */
if(!(lg = logget((unsigned char *)argv[i] + 2, NONE))){
if(!(lg = logget((unsigned char *)argv[i] + 2, NONE, &err))){
fprintf(stderr, "Unable to open log %.*s: %s\n",
(int)logselen((unsigned char *)argv[i] + 2), argv[i] + 2, strerror(errno));
(int)logselen((unsigned char *)argv[i] + 2), argv[i] + 2, strerror(err));
return 1;
}
logput(srv->logger);

View File

@ -346,7 +346,7 @@ void logdo(struct clientparam * param, const unsigned char *s);
void logerror(const unsigned char *s);
void loginit(void);
void logtypeadd(const struct logtype *type);
struct logger *logget(const unsigned char *selector, ROTATION rotation);
struct logger *logget(const unsigned char *selector, ROTATION rotation, int *errp);
void logref(struct logger *lg);
void logput(struct logger *lg);
void logcommit(struct extparam *c);

View File

@ -101,7 +101,7 @@ static int odbcmatch(const unsigned char *selector){
/* A data source down is not an error of the configuration: the log
connects again later. */
static int odbcinit(struct logger *lg){
if(!lg->data && !(lg->data = calloc(1, sizeof(struct logodbc)))) return 21;
if(!lg->data && !(lg->data = calloc(1, sizeof(struct logodbc)))) return ENOMEM;
return odbcconnect(lg)? 0 : -1;
}

View File

@ -635,8 +635,8 @@ struct hashtable {
struct logtype {
const char *name;
int (*match)(const unsigned char *selector);
/* opens what it writes to, lg->data: 0, an error, or < 0 if it cannot
be reached now but is to be tried again */
/* opens what it writes to, lg->data: 0, an error (an errno value), or
< 0 if it cannot be reached now but is to be tried again */
int (*init)(struct logger *lg);
/* the line for a connection into buf, CLIENTTMPBUFSIZE: its length, -1
for nothing to write; NULL if write() takes the connection itself */