0

I am working with pthreads in c++ doing the sleeping barber problem. Was just trying to initialize threads and test it out but am getting a segmentation fault at a random point in execution. Sometimes both threads are able to output and sometimes only one thread is able to output. I am struggling to find what's causing this in my current code. Any help is greatly appreciated <3

#include <iostream>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

using namespace std;

#define NUM_THREADS 2

// Global pthread implementation of mutex lock
pthread_mutex_t mtx;

// Argument we will cast as void* for the thread function
struct Args {
  int tid;
  string type;
};

void *test_thread_function(void *args) {
  Args *local_args = (Args *)args;
  // Get the lock before entering the critical section
  pthread_mutex_lock(&mtx);
  cout << "Printing from thread " << local_args->tid << endl;
  cout << "Value of type is " << local_args->type << endl;
  // Release the lock to someone else
  pthread_mutex_unlock(&mtx);
}

int main() {
  // Create an array of threads
  pthread_t threads[NUM_THREADS];
  Args per_thread_args[NUM_THREADS];

  // Create threads
  for (int i = 0; i < NUM_THREADS; i++) {
    if (i == 0){ //barber thread creation
      per_thread_args[i].tid = 0;
      per_thread_args[i].type = "barber";
      pthread_create(&threads[i], NULL, test_thread_function, (void *)&per_thread_args[i]);
    } else { //customer thread creation
      per_thread_args[i].tid = 1;
      per_thread_args[i].type = "customer";
      pthread_create(&threads[i], NULL, test_thread_function, (void *)&per_thread_args[i]);
    }
    // Launch the threads
    /*
        Arguments:
            1.) Pointer to pthread_t
            2.) Attributes for the thread (NULL means default)
            3.) Entry routine
            4.) Arguments
    */
  }
  
  // Return code for the thread
  void *ret;
  // Wait for all threads to finish before exiting the program
  for (int i = 0; i < NUM_THREADS; i++) {
    pthread_join(threads[i], &ret);
  }

  return 0;
}
  • 5
    [Resolve the warning here](https://godbolt.org/z/nd8Pz1dG8) and see if you still have a problem. – user4581301 Mar 30 '23 at 22:18
  • 1
    Tangential: any reason not to use `std::thread`? – Paul Sanders Mar 30 '23 at 22:19
  • 2
    O/T unless you're forced into using an ancient version of c++, better to use `std::thread` and friends instead – yano Mar 30 '23 at 22:19
  • 4
    looks like you're missing [`pthread_mutex_t` initialization](https://stackoverflow.com/questions/14320041/pthread-mutex-initializer-vs-pthread-mutex-init-mutex-param) – yano Mar 30 '23 at 22:24
  • @user4581301 I honestly was not sure how to resolve that warning but adding a return 0 at the end of the function did solve the issue it seems, what's the reason for this if you don't mind me asking? –  Mar 30 '23 at 22:25
  • @PaulSanders We are forced to use Posix threads, honestly not entirely sure which to use at the moment. Removing the * causes a lot of errors, im very new to multi threading w pthreads and c++ so my apologies. –  Mar 30 '23 at 22:27
  • 1
    _Removing the * causes a lot of errors_ Yes, sorry, you need it (deleted my comment) – Paul Sanders Mar 30 '23 at 22:27
  • 2
    Compilers can do weird things if you leave out the `return` statement even if you never use the returned value. The behaviour of Undefined Behaviour is undefined, and all that. Playing around with Compiler Explorer a bit more you can see that the generated code with and without the `return NULL;` is very, very different: [with](https://godbolt.org/z/rccEfssbq) and [without](https://godbolt.org/z/77bP9hGfv) The function's half the size without the `return`. – user4581301 Mar 30 '23 at 22:49
  • @user4581301 Interesting. I've never understood why a missing `return` statement isn't a hard error. – Paul Sanders Mar 30 '23 at 23:54
  • @PaulSanders Agreed, but it probably has to do with difficulties in getting the compiler to reliably detect a function that doesn't exit in all the possible cases. – user4581301 Mar 31 '23 at 00:05
  • 2
    @JakeDAmico *"adding a return 0"* -- returning `nullptr` is a better fit for the declared return type (pointer-to-`void`). – JaMiT Mar 31 '23 at 00:11
  • @PaulSanders *"I've never understood why a missing return statement isn't a hard error."* -- Just tell everyone that `-Werror=return-type` is mandatory. :) *Edit: Looks like this question has some answers: [Why does flowing off the end of a non-void function without returning a value not produce a compiler error?](https://stackoverflow.com/q/1610030)* – JaMiT Mar 31 '23 at 00:13
  • Does this answer your question? [Why the executable produced in "release " mode gives a bad result?](https://stackoverflow.com/questions/36647598/why-the-executable-produced-in-release-mode-gives-a-bad-result) (I admit it is vague about how the program "fails", but it is the same root cause and the answers are applicable.) – JaMiT Mar 31 '23 at 00:21

0 Answers0