PunyCode
PunyCode

Reputation: 373

Segmentation fault while calling globfree()

[using arm-hisiv300-linux-gcc to compile for Linux based Target board]

I got segmentation fault while I called this function.

uint32_t dir_disp(void)
{
    uint32_t        err;
    uint32_t        i;
    size_t          cnt;
    char            *str;
    char            **p;

    glob_t          glob_results;   

    err = glob("/home/2019-11-12/H*", GLOB_MARK, 0, &glob_results);

    p = glob_results.gl_pathv;
    cnt = glob_results.gl_pathc;

    for (i=0; i<cnt; i++)
    {
        printf("[DEBUG] dir_disp: %s\n",p[i]);
    }

    globfree(&glob_results);
    return 0;
}

the above function is called only once from a thread function, the segmentation fault occurred only when there are more than ~100 items matching the pattern "/home/2019-11-12/H*"

Segmentation fault doesn't occur if:

[Edit]

Sorry but I forgot to mention the segfault occur only after printing all the items matching the pattern.

I checked the ret val of glob() and found it to be zero. Not changing the original question.

Upvotes: 0

Views: 483

Answers (2)

rici
rici

Reputation: 241861

According to the Linux manpage, glob() is not MT-safe so it is "not safe to call in a multithreaded program".

It's possibly worth noting that Posix does require glob() to be MT-safe, so this attribute is specific to the Gnu implementation in glibc, and might have to do with Gnu extensions such as the tilde expansion option. All the same, you should be aware of the warning.

Based on the symptoms you report, a possible issue is stack overflow, perhaps related to the use of alloca or VLAs in the glob implementation. (I didn't check the source code, though; I have no particular evidence that such features are actually used.) Default stack sizes in multithreaded code tend to be quite small, and code which works fine in a non-MT environment can easily exceed the stack size of a default thread. You could try increasing the stack size when you create the thread(s) which call glob.

Upvotes: 1

user3629249
user3629249

Reputation: 16540

the following proposed code:

  1. cleanly compiles
  2. performs the desired functionality

Notice how the first parameter to glob() is written

and now, the proposed code:

#include <stdint.h>
#include <glob.h>
#include <stdio.h>


uint32_t dir_disp(void)
{
    int             err;
    size_t          cnt;
    char            **p;

    glob_t          glob_results;   

    err = glob("/home/richard/*", GLOB_MARK, 0, &glob_results);

    printf( "err: %d\n", err );

    p = glob_results.gl_pathv;
    cnt = glob_results.gl_pathc;

    for (size_t i=0; i<cnt; i++)
    {
        printf("[DEBUG] dir_disp: %s\n",p[i]);
    }

    globfree(&glob_results);
    return 0;
}


int main( void )
{
    uint32_t result = dir_disp();
    printf( "result: %d\n", result );
}

a run of the above code results in:

err: 0
[DEBUG] dir_disp: /home/richard/Desktop/
[DEBUG] dir_disp: /home/richard/Documents/
[DEBUG] dir_disp: /home/richard/Downloads/
[DEBUG] dir_disp: /home/richard/Music/
[DEBUG] dir_disp: /home/richard/OpenMPI/
[DEBUG] dir_disp: /home/richard/Pictures/
[DEBUG] dir_disp: /home/richard/Public/
[DEBUG] dir_disp: /home/richard/Templates/
[DEBUG] dir_disp: /home/richard/Videos/
[DEBUG] dir_disp: /home/richard/examples.desktop
result: 0

there were lots of other directories, but they are not relevant to this answer

Upvotes: 0

Related Questions