Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pthread and fopen64 segfaults on fgets

I'm using Kubuntu 12.04, gcc 4.6.3. If I create a pthread, use fopen64 and then fgets - it segfaults. Same code replacing fopen64 with fopen - it succeeds. Without creating pthread - it succeeds. So why the failure? Here's the code:

#include <stdio.h>
#include <pthread.h>
typedef struct threadArgs
{
    char* argsList;
    int argc;
} threadArgs;

void 
threadRun(void *pArg);

int
main(int argc, char* argv[])
{
    int err = 0;
    threadArgs thrArgs;
    pthread_t thrd;  

    if (argc > 1)
    {
        printf("creating thread \n");
        err = pthread_create (&thrd, NULL, (void *) &threadRun, (void *) &thrArgs);
        printf("pthread_create returned: %d \n", err);
        pthread_join(thrd, NULL);
    }
    else
    {
        printf("no thread - just calling func \n");
        threadRun((void*)&thrArgs);
    }
    printf("Exiting main() \n");

    return err;
}

void 
threadRun(void *pArg)
{
    printf("IN the Thread \n");
    char* pStr;
    FILE *pFile = NULL;

    pFile = (FILE*)fopen64("test.txt","r");
    //pFile = (FILE*)fopen("test.txt","r");

    if (pFile==NULL)
    {
        printf("pFile is NULL \n");
    }
    else
    {
        printf("pFile is NOT null \n");
        char line[256];
        pStr = fgets(line, sizeof(line),pFile);
        if (pStr)
        {
            printf("line retrieved: %s \n", line);
        }
        else
        {
            printf("no line retrieved \n");
        }
    }   

    printf("End of pthread run func \n");
    return;
}
like image 218
Skippy VonDrake Avatar asked Nov 09 '12 17:11

Skippy VonDrake


1 Answers

pthread_create() expects void * (*)(void *) as thread function, but you are passing void (*)(void *).


Update:

You are missing a prototype for fopen64(), so the compiler assumes int which is not the same as FILE*.


Update 1:

To have this prototype available (and with this fix you initial problem) just add:

#define _LARGEFILE64_SOURCE

as first line in your source file.

Additional edit: To be exact: _LARGEFILE64_SOURCE needs to #defineed before #includeing stdio.h


Update 2:

Following the sources I used to make the suxxer work (main.c):

#define _LARGEFILE64_SOURCE

#include <stdio.h>
#include <pthread.h>

typedef struct threadArgs
{
    char* argsList;
    int argc;
} threadArgs;

void *
threadRun(void *pArg);

int
main(int argc, char* argv[]) /* line 16 */
{
    int err = 0;
    threadArgs thrArgs;
    pthread_t thrd;

    if (argc > 1)
    {
        printf("creating thread \n");
        err = pthread_create (&thrd, NULL, threadRun, &thrArgs);
        printf("pthread_create returned: %d \n", err);
        pthread_join(thrd, NULL);
    }
    else
    {
        printf("no thread - just calling func \n");
        threadRun((void*)&thrArgs);
    }
    printf("Exiting main() \n");

    return err;
}

void  *
threadRun(void *pArg)  /* line 40 */
{
    printf("IN the Thread \n");
    char* pStr;
    FILE *pFile = NULL;

    pFile = fopen64("test.txt","r");

    if (pFile==NULL)
    {
        printf("pFile is NULL \n");
    }
    else
    {
        printf("pFile is NOT null \n");
        char line[256];
        pStr = fgets(line, sizeof(line),pFile);
        if (pStr)
        {
            printf("line retrieved: %s \n", line);
        }
        else
        {
            printf("no line retrieved \n");
        }
    }

    printf("End of pthread run func \n");

    return 0;
}

build by:

$gcc -Wall -g -o main main.c -pedantic -Wextra -std=c99 -pthread 
main.c: In function ‘main’:
main.c:16: warning: unused parameter ‘argv’
main.c: In function ‘threadRun’:
main.c:40: warning: unused parameter ‘pArg’

(no other errors or warnings)

enviroment:

$ uname -a
Linux debian-stable 2.6.32-5-amd64 #1 SMP Sun Sep 23 10:07:46 UTC 2012 x86_64 GNU/Linux
$ gcc --version
gcc (Debian 4.4.5-8) 4.4.5
[...]
$ ldd main
        linux-vdso.so.1 =>  (0x00007fff466d6000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x00007f15ccd20000)
        ibc.so.6 => /lib/libc.so.6 (0x00007f15cc9be000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f15ccf4b000)

The output (using main.c's source without \ns as test.txt):

$ valgrind ./main 1
==31827== Memcheck, a memory error detector
==31827== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==31827== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==31827== Command: ./main 1
==31827== 
creating thread 
pthread_create returned: 0 
IN the Thread 
pFile is NOT null 
line retrieved: #define _LARGEFILE64_SOURCE #include <stdio.h> #include <pthread.h> typedef struct threadArgs { char* argsList; int argc; } threadArgs; void * threadRun(void *pArg); int main(int argc, char* argv[]) { int err = 0; threadArgs thrArgs; pthread_t thrd; if (a 
End of pthread run func 
Exiting main() 
==31827== 
==31827== HEAP SUMMARY:
==31827==     in use at exit: 568 bytes in 1 blocks
==31827==   total heap usage: 2 allocs, 1 frees, 840 bytes allocated
==31827== 
==31827== LEAK SUMMARY:
==31827==    definitely lost: 0 bytes in 0 blocks
==31827==    indirectly lost: 0 bytes in 0 blocks
==31827==      possibly lost: 0 bytes in 0 blocks
==31827==    still reachable: 568 bytes in 1 blocks
==31827==         suppressed: 0 bytes in 0 blocks
==31827== Rerun with --leak-check=full to see details of leaked memory
==31827== 
==31827== For counts of detected and suppressed errors, rerun with: -v
==31827== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
like image 189
alk Avatar answered Nov 08 '22 18:11

alk