0

This piece of code seems to throw a segmentation fault, but if the pthread_create line is commented out, the segfault disappears.

pthread_t thread_id[device_count];

if (params.revision == 3) {
    startTime = time(NULL);
    unsigned long number = 0;

    deviceParams = get_device_params(platform_id, workWithUser ? "check_pdfs_user" : "check_pdfs_owner", program_buffer, program_size);

    int password_len = strlen(password_prefix) + password_digits + strlen(password_suffix);

    int j;

    unsigned long password_per_thread;

    password_t password;
    char pad[33];
    sprintf(pad, "%%s%%0%dd%%s", password_digits);

    while (number < max_password) {
        // how many passwords need to be generated
        password_per_thread = (max_password - number) / device_count;
        if (password_per_thread > batch_size)
            password_per_thread = batch_size;

        pthread_mutex_init(&lock, NULL);
        ThreadArg thread_arg;

        for (j = 0; j < device_count; j++) {
            // for (i = 0; i < password_per_thread; i++) {
            //  password.size_bytes = password_len;
            //  sprintf(password.password, pad, password_prefix, number++, password_suffix);
            //  numbers[i] = password;
            // }
            printf("%d\n", j);
            thread_arg.device_params = deviceParams[j];
            printf("A2\n");
            thread_arg.pdf_params = params;
            printf("1\n");
            thread_arg.start = number;
            printf("2\n");
            thread_arg.prefix = password_prefix;
            printf("3\n");
            thread_arg.prefix_length = strlen(password_prefix);
            printf("4\n");
            thread_arg.suffix = password_suffix;
            printf("5\n");
            thread_arg.suffix_length = strlen(password_suffix);
            thread_arg.length = password_len;
            thread_arg.count = password_per_thread;
            printf("6\n");
            pthread_create(&thread_id[j], NULL, runOnThread, &thread_arg);
        }
        void *status;
        for (i = 0; i < device_count; i++) {
            pthread_join(thread_id[i], &status);
            if ((bool *) status) {
                found = true;
            }
        }
        if (found) {
            break;
        }
    }
}

The segfault happens on:

thread_arg.device_params = deviceParams[j];

but if the following line is commented, then the segfault disappears:

pthread_create(&thread_id[j], NULL, runOnThread, &thread_arg);

This is segfault:

Thread 2 received signal SIGSEGV, Segmentation fault.
0x000000010000113b in runCrack () at pdfcrack.c:138
138                 thread_arg.device_params = deviceParams[j];

Here's the output of gdb bt:

(gdb) bt
#0  0x000000010000113b in runCrack () at pdfcrack.c:138
#1  0x0000000100000bf6 in main (argc=<optimized out>, argv=0x7ffeefbff9c8) at main.c:250
Amit
  • 3,952
  • 7
  • 46
  • 80

1 Answers1

1

You should not reuse thread_arg like you do, that will cause a data race. Use an array of such arg instead. See

how not to use the pthread_create arg

Here is a simple example of the race, on my machine it prints 2, then 3, then 3.

#include <pthread.h>
#include <stdexcept>
#include <iostream>

using std::cout;

const int NR_THREADS = 3;
pthread_t tid[NR_THREADS];

void* threadfunc(void* arg)
{
    int val = *(int* )arg;

    cout << "Thread got arg " << val << '\n';

    return 0;
}

int main()
{
    int retval;

    for (int i = 0; i < NR_THREADS; i++) {
        retval = pthread_create(&tid[i], NULL, threadfunc, &i);
        if (retval) throw std::runtime_error("Pthread create failed!");
    }

    for (int i = 0; i < NR_THREADS; i++) {
        pthread_join(tid[i], NULL);
        if (retval) throw std::runtime_error("Pthread join failed!");
    }

    return 0;
}

Here is the diff I needed to avoid build errors (also had to change header locations and .so lib location on Ubuntu, and remove the -framework gcc flag)

diff pdfcrack/pdfcrack.c pdfcrack_modded/pdfcrack.c
116c116
<       pthread_t thread_id = malloc(sizeof(pthread_t) * device_count);
---
>       pthread_t* thread_id = malloc(sizeof(pthread_t) * device_count);
154c154
<               pthread_join(&thread_id[i], &status);
---
>               pthread_join(thread_id[i], &status);
Erik Alapää
  • 2,585
  • 1
  • 14
  • 25
  • Post a minimal, complete example that SO users can try out, debug and modify. – Erik Alapää Jul 25 '18 at 10:43
  • Here's a link... Can't make it any more minimal, as I am not sure where in here is the error.... https://drive.google.com/drive/folders/1obqU7pmehm41664JLl2uRJKq6MBpE-lt?usp=sharing After making this, run it with, pdfcrack -d 1 /path/to/a/pdf/file – Amit Jul 25 '18 at 11:04
  • Have you checked the return from clGetDeviceIDs? How many devices do you get? I do not have OpenCL and possibly other dependencies needed to build. – Erik Alapää Jul 25 '18 at 11:14
  • Yep, that's giving me 1 device. Infact a version of this code was working until last night, not even sure what changed! – Amit Jul 25 '18 at 12:21
  • I managed to compile and run your code now, adding diff in the answer, try changing like I changed. I have no encrypted pdf to test with. – Erik Alapää Jul 25 '18 at 13:15
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/176723/discussion-between-erik-alapaa-and-amit). – Erik Alapää Jul 25 '18 at 13:19
  • Your diff was definitely one of the underlying errors I guess, but the issue didn't get solved completely. I ended up rewriting the whole thing now... seems to be working! – Amit Jul 26 '18 at 15:43
  • Congrats, nice to get the code working, albeit by a rewrite! – Erik Alapää Jul 26 '18 at 15:45