Skip to content

Commit 68079be

Browse files
authored
fix: add procfile parsing for non-seekable files (#21507)
1 parent 073d5fd commit 68079be

File tree

2 files changed

+26
-11
lines changed

2 files changed

+26
-11
lines changed

src/libnetdata/procfile/procfile.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -330,14 +330,29 @@ procfile *procfile_readall(procfile *ff) {
330330

331331
ff->len += r;
332332
}
333-
334-
// netdata_log_debug(D_PROCFILE, "Rewinding file '%s'", ff->filename);
335-
if(unlikely(lseek(ff->fd, 0, SEEK_SET) == -1)) {
336-
if(unlikely(!(ff->flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) collector_error(PF_PREFIX ": Cannot rewind on file '%s'.", procfile_filename(ff));
337-
else if(unlikely(ff->flags & PROCFILE_FLAG_ERROR_ON_ERROR_LOG))
338-
netdata_log_error(PF_PREFIX ": Cannot rewind on file '%s'.", procfile_filename(ff));
339-
procfile_close(ff);
340-
return NULL;
333+
334+
if (unlikely(ff->flags & PROCFILE_FLAG_NONSEEKABLE)) {
335+
char *fn = procfile_filename(ff);
336+
ff = procfile_reopen(ff, fn, NULL, ff->flags);
337+
if (unlikely(!ff))
338+
return NULL;
339+
} else if (unlikely(lseek(ff->fd, 0, SEEK_SET) == -1)) {
340+
// Some procfs files (Ubuntu HWE 24.04 / kernel 6.14) may be non-seekable.
341+
// In that case, "rewind" by reopening.
342+
if (errno == ESPIPE || errno == EINVAL) {
343+
ff->flags |= PROCFILE_FLAG_NONSEEKABLE;
344+
char *fn = procfile_filename(ff);
345+
ff = procfile_reopen(ff, fn, NULL, ff->flags);
346+
if (unlikely(!ff))
347+
return NULL;
348+
} else {
349+
if (unlikely(!(ff->flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO)))
350+
collector_error(PF_PREFIX ": Cannot rewind on file '%s'.", procfile_filename(ff));
351+
else if (unlikely(ff->flags & PROCFILE_FLAG_ERROR_ON_ERROR_LOG))
352+
netdata_log_error(PF_PREFIX ": Cannot rewind on file '%s'.", procfile_filename(ff));
353+
procfile_close(ff);
354+
return NULL;
355+
}
341356
}
342357

343358
procfile_lines_reset(ff->lines);
@@ -498,9 +513,8 @@ procfile *procfile_reopen(procfile *ff, const char *filename, const char *separa
498513
}
499514
ff->stats.opens++;
500515

501-
// netdata_log_info("PROCFILE: opened '%s' on fd %d", filename, ff->fd);
502-
503-
//strncpyz(ff->filename, filename, FILENAME_MAX);
516+
// IMPORTANT: 'filename' parameter must not be used after this point
517+
// as it may point to ff->filename which we're about to free
504518
freez(ff->filename);
505519
ff->filename = NULL;
506520
ff->flags = flags;

src/libnetdata/procfile/procfile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ typedef struct {
3636
#define PROCFILE_FLAG_DEFAULT 0x00000000 // To store inside `collector.log`
3737
#define PROCFILE_FLAG_NO_ERROR_ON_FILE_IO 0x00000001 // Do not log anything
3838
#define PROCFILE_FLAG_ERROR_ON_ERROR_LOG 0x00000002 // Store inside `error.log`
39+
#define PROCFILE_FLAG_NONSEEKABLE 0x00000004 // File doesn't support lseek(), reopen instead
3940

4041
typedef enum __attribute__ ((__packed__)) procfile_separator {
4142
PF_CHAR_IS_SEPARATOR,

0 commit comments

Comments
 (0)