• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

saitoha / libsixel / 21602244167

02 Feb 2026 06:23PM UTC coverage: 77.475% (-0.01%) from 77.487%
21602244167

push

github

saitoha
build: fix for mingw64-make

23661 of 50520 branches covered (46.83%)

37662 of 48612 relevant lines covered (77.47%)

40022585.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

42.17
/src/logger.c
1
/*
2
 * SPDX-License-Identifier: MIT
3
 *
4
 * Copyright (c) 2025 libsixel developers. See `AUTHORS`.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 * SOFTWARE.
23
 */
24

25
#if defined(HAVE_CONFIG_H)
26
#include "config.h"
27
#endif
28

29
#include <stdint.h>
30
#include <stdio.h>
31
#include <stdlib.h>
32
#include <string.h>
33

34
#ifndef _WIN32
35
#include <pthread.h>
36
#endif
37

38
#include "logger.h"
39
#include "timer.h"
40
#include "compat_stub.h"
41

42
static sixel_logger_t *sixel_logger_active;
43
static int sixel_logger_refcount;
44

45
static unsigned long long
46
sixel_logger_thread_id(void)
47
{
48
#ifndef _WIN32
49
    return (unsigned long long)(uintptr_t)pthread_self();
50
#else
51
    return 0ULL;
52
#endif
53
}
54

55
void
56
sixel_logger_init(sixel_logger_t *logger)
510,286✔
57
{
58
    if (logger == NULL) {
413,402!
59
        return;
60
    }
61
    logger->delegate = NULL;
510,286✔
62
    logger->file = NULL;
510,286✔
63
    logger->mutex_ready = 0;
510,286✔
64
    logger->active = 0;
510,286✔
65
    logger->started_at = 0.0;
413,402✔
66
}
237,773✔
67

68
void
69
sixel_logger_close(sixel_logger_t *logger)
240,787✔
70
{
71
    if (logger == NULL) {
240,787!
72
        return;
73
    }
74
    if (logger->delegate != NULL) {
240,787!
75
        if (logger->delegate == sixel_logger_active &&
×
76
                sixel_logger_refcount > 0) {
×
77
            --sixel_logger_refcount;
×
78
            if (sixel_logger_refcount != 0) {
×
79
                logger->delegate = NULL;
×
80
                logger->active = 0;
×
81
                return;
×
82
            }
83
            logger = logger->delegate;
×
84
            logger->delegate = NULL;
×
85
        } else {
86
            logger->delegate = NULL;
×
87
            logger->active = 0;
×
88
            return;
×
89
        }
90
    }
91
    if (logger == sixel_logger_active && sixel_logger_refcount > 1) {
240,787!
92
        --sixel_logger_refcount;
×
93
        return;
×
94
    }
95
    if (logger->mutex_ready) {
240,787!
96
#if SIXEL_ENABLE_THREADS
97
        sixel_mutex_destroy(&logger->mutex);
98
#endif  /* SIXEL_ENABLE_THREADS */
99
        logger->mutex_ready = 0;
×
100
    }
101
    if (logger->file != NULL) {
240,787!
102
        fclose(logger->file);
×
103
        logger->file = NULL;
×
104
    }
105
    if (logger == sixel_logger_active && sixel_logger_refcount > 0) {
240,787!
106
        sixel_logger_refcount = 0;
×
107
        sixel_logger_active = NULL;
×
108
    }
109
    logger->active = 0;
240,787✔
110
}
111,608✔
111

112
SIXELSTATUS
113
sixel_logger_open(sixel_logger_t *logger, char const *path)
×
114
{
115
    if (logger == NULL) {
×
116
        return SIXEL_BAD_ARGUMENT;
117
    }
118
    if (path == NULL || path[0] == '\0') {
×
119
        return SIXEL_OK;
120
    }
121
    logger->file = sixel_compat_fopen(path, "w");
×
122
    if (logger->file == NULL) {
×
123
        return SIXEL_RUNTIME_ERROR;
124
    }
125
#if SIXEL_ENABLE_THREADS
126
    if (sixel_mutex_init(&logger->mutex) != 0) {
×
127
        fclose(logger->file);
128
        logger->file = NULL;
129
        return SIXEL_RUNTIME_ERROR;
130
    }
131
#endif  /* SIXEL_ENABLE_THREADS */
132
    logger->mutex_ready = 1;
×
133
    logger->active = 1;
×
134
    logger->started_at = sixel_timer_now();
×
135
    /*
136
     * Use fully buffered output to avoid newline-triggered flushes.  VPTE
137
     * timeline logging can emit many events, and line buffering would force
138
     * frequent kernel writes even without explicit fflush() calls.
139
     */
140
    setvbuf(logger->file, NULL, _IOFBF, 0);
×
141
    sixel_logger_active = logger;
×
142
    sixel_logger_refcount = 1;
×
143
    return SIXEL_OK;
×
144
}
145

146
SIXELSTATUS
147
sixel_logger_prepare_env(sixel_logger_t *logger)
253,527✔
148
{
149
    char const *path;
194,627✔
150
    SIXELSTATUS status;
194,627✔
151

152
    if (logger == NULL) {
253,527!
153
        return SIXEL_BAD_ARGUMENT;
154
    }
155

156
    /*
157
     * Reuse an already opened logger so the timeline is continuous.  Some
158
     * call sites share a logger instance across serial and pipeline phases;
159
     * reopening would truncate the file and reset timestamps, hiding early
160
     * stages from the timeline. Share the sink via a lightweight delegate
161
     * pointer instead of copying mutex state.
162
     */
163
    if (sixel_logger_active != NULL &&
253,527!
164
            sixel_logger_active->active &&
×
165
            sixel_logger_active->mutex_ready) {
×
166
        sixel_logger_init(logger);
×
167
        logger->delegate = sixel_logger_active;
×
168
        logger->active = sixel_logger_active->active;
×
169
        logger->started_at = sixel_logger_active->started_at;
×
170
        ++sixel_logger_refcount;
×
171
        return SIXEL_OK;
×
172
    }
173

174
    sixel_logger_init(logger);
253,527✔
175
    path = sixel_compat_getenv("SIXEL_LOG_PATH");
253,527✔
176
    if (path == NULL || path[0] == '\0') {
253,527!
177
        return SIXEL_OK;
118,015✔
178
    }
179
    status = sixel_logger_open(logger, path);
×
180
    if (SIXEL_FAILED(status)) {
×
181
        sixel_logger_close(logger);
×
182
    }
183

184
    return status;
185
}
117,972✔
186

187
void
188
sixel_logger_logf(sixel_logger_t *logger,
1,136,804✔
189
                           char const *role,
190
                           char const *worker,
191
                           char const *event,
192
                           int job_id,
193
                           ...)
194
{
195
    sixel_logger_t *target;
875,211✔
196
    double timestamp;
875,211✔
197

198
    /*
199
     * Extra arguments are accepted for compatibility with older call sites
200
     * but intentionally ignored to keep timeline logging lightweight.
201
     */
202
    target = logger;
1,136,804✔
203
    if (logger != NULL && logger->delegate != NULL) {
1,136,804!
204
        target = logger->delegate;
×
205
    }
206
    if (target == NULL || !target->active || target->file == NULL
1,136,804!
207
            || !target->mutex_ready) {
×
208
        return;
533,884✔
209
    }
210

211
#if SIXEL_ENABLE_THREADS
212
    sixel_mutex_lock(&target->mutex);
213
#endif  /* SIXEL_ENABLE_THREADS */
214
    timestamp = sixel_timer_now() - target->started_at;
×
215
    if (timestamp < 0.0) {
×
216
        timestamp = 0.0;
217
    }
218
    fprintf(target->file,
×
219
            "{\"ts\":%.6f,\"thread\":%llu,\"worker\":\"%s\","\
220
            "\"role\":\"%s\",\"event\":\"%s\",\"job\":%d}\n",
221
            timestamp,
222
            sixel_logger_thread_id(),
223
            worker != NULL ? worker : "",
×
224
            role != NULL ? role : "",
×
225
            event != NULL ? event : "",
×
226
            job_id);
227
    fflush(target->file);
×
228
#if SIXEL_ENABLE_THREADS
229
    sixel_mutex_unlock(&target->mutex);
230
#endif  /* SIXEL_ENABLE_THREADS */
231
}
533,884!
232

233
/* emacs Local Variables:      */
234
/* emacs mode: c               */
235
/* emacs tab-width: 4          */
236
/* emacs indent-tabs-mode: nil */
237
/* emacs c-basic-offset: 4     */
238
/* emacs End:                  */
239
/* vim: set expandtab ts=4 sts=4 sw=4 : */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc