1
votes

This seems like a very simple problem but I really can't figure what is going wrong here. I have written a logging function and a main function that starts a thread which repeatedly calls that function. the call to open succeeds and the file descriptor does not become corrupted before the call to write. still no bytes are written and errno is set to BAD FILE DESCRIPTOR. (I've omitted most error checks for readbility)

logging function:

static pthread_once_t once = PTHREAD_ONCE_INIT;
static int logfd;

static void _log_init(void)
{
    int flags = O_CREAT | O_TRUNC | O_APPEND;
    int perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;

    logfd = open("log.txt", flags, perms);
}

void log_data(const char *fmt, ...)
{
    int bufsize;
    char *buf;

    pthread_once(&once, _log_init);

    va_list va;

    va_start(va, fmt);
    bufsize = vsnprintf(NULL, 0, fmt, va) + 1;
    va_end(va);

    va_start(va, fmt);
    vsnprintf(buf, bufsize, fmt, va);
    va_end(va);

    if (write(logfd, buf, bufsize) == -1)
        perror("write");

    free(buf);
}

main function:

static void *thread_log(void *arg)
{
    int thread = *((int *)arg);
    free(arg);

    for (int i = i; i < 10; ++i)
        log_data("thread %d\n", thread);

    return (void *) NULL;
}

int main()
{
    pthread_t t;
    int *arg;

    arg = malloc(sizeof(int));
    *arg = 1;
    pthread_create(&t, NULL, thread_log, (void *) arg);

    pthread_join(t, NULL);

    return 0;
}
2
For the record, you use stdarg.h for your argument list. The file descriptor is created using the open function from fcntl.h. Then write from unistd.h. What value is your file descriptor after open? Does it change between calls? When you say it's "corrupted", do you mean it turns invalid or does it actually change value?starturtle

2 Answers

0
votes

I see a couple of problems.

First, you never allocated buf. You calculated a size for it, and even freed it, but when you actually write to it, it's still uninitialized.

Second, when you need to reuse a va_list, you're supposed to make a copy with va_copy. The state after the first va_end is not guaranteed to be appropriate for a second va_start.

0
votes

You need to add O_WRONLY to open flags, otherwise you won't have the right to write on this file descriptor.

int flags = O_CREAT | O_TRUNC | O_APPEND | O_WRONLY;

You also have a couple of things you need to fix on this code such as initializing i (you're currently doing int i = i) and buf.