Thread: Need some help debugging

  1. #1
    Registered User
    Join Date
    Jun 2008
    Posts
    15

    Need some help debugging

    Don't mind the commenting of code, I just switched my implementation around so that's why a lot of things are commented out. My problem lies in the "quitting" of the program. The program reads from standard input until the letter 'q' or 'Q' (upper or lower case) is entered, than quits and signals the other threads to shut down. It technically works because I get a segmentation fault ...but in the real world that doesn't count. Can anyone have a look and help me figure out whats wrong, i've tried debugging with no luck (not sure how to do it with threads in gdb). But anyways, so program runs fine until command 'Q' or 'q' is entered, than exits due to segmentation fault. Thanks in advance. The only thing I can think of is probably the way i'm shutting down the threads...

    Code:
    //   To compile: gcc -lpthread -lrt program.c
    
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <semaphore.h>
    
    //Definitions
    #define NOTSHARED 0
    #define BUFFSIZE 81
    
    //Type
    typedef enum { FALSE, TRUE } boolean;
    
    //Function prototypes
    void *inputFcn( void *id );
    void *processFcn( void *id );
    void *outputFcn( void *id );
    
    //Globals (shared data)
    char *operator1;
    
    int operand1, operand2, result;
    
    boolean quit = FALSE;
    
    //mutex's
    //pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
    //pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
    //pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER;
    
    // the semaphores used to coordinate thread activity
    sem_t semaphore1, semaphore2, semaphore3;
    
    int main( int argc, char *argv[] )
    {
       pthread_t input, process, output;
    
       // Since mutex are initially unlocked, we lock them...
       //pthread_mutex_lock( &mutex1 );
       //pthread_mutex_lock( &mutex2 );
       //pthread_mutex_lock( &mutex3 );
    
       // initialize the semaphores
       sem_init( &semaphore1, NOTSHARED, 0 );
       sem_init( &semaphore2, NOTSHARED, 0 );
       sem_init( &semaphore3, NOTSHARED, 0 );
    
       // Creating thread...
       pthread_create( &input, NULL, inputFcn, NULL );
       pthread_create( &process, NULL, processFcn, NULL );
       pthread_create( &output, NULL, outputFcn, NULL );
    
       pthread_exit( NULL );
    }
    
    
    void *inputFcn( void *id )
    {
    	char buffer[ BUFFSIZE ]; // room for 80 chars plus \0
    	char *input;
    
    	input = fgets( buffer, BUFFSIZE, stdin );
    	while( *input != 'q' || *input != 'Q' )// && quit == FALSE ) //&& strstr( input, "q" ) == NULL && strstr( input, "Q" ) == NULL )
      	{
    		//Format of string will be error free and
    		//in the format 'operand operator operand'
    		//convert operand's to integers
    
    		//if( *input == 'q' || *input == 'Q' )//input[0] == 'q' || input[0] == 'Q' )
    		//	quit = TRUE;
    
    		operand1 = atoi( strtok( input, " " ) ); //write first operand to shared data
    		operator1 = strtok( NULL, " " );         //write operator to shared data
    		operand2 = atoi( strtok( NULL, " " ) );    //write second operand to shared data
    
    		//pthread_mutex_unlock( &mutex2 );
    		//pthread_mutex_lock( &mutex1 );
    		sem_post( &semaphore2 );
    		sem_wait( &semaphore1 );
    
    		input = fgets( buffer, BUFFSIZE, stdin );
    
    	}
    
    	quit = TRUE;
    
    	pthread_exit( NULL );
    }
    
    void *processFcn( void *id )
    {
    	while( quit == FALSE )
    	{
    		//pthread_mutex_lock( &mutex2 );
    	    sem_wait( &semaphore2 );
    
    		switch ( operator1[0] )                  /* select the type of calculation */
        	{
    			case '+':
    				result = operand1 + operand2;
    				break;
    			case '-':
    				result = operand1 - operand2;
    				break;
    			case '*':
    				result = operand1 * operand2;
    				break;
    			case '/':
    				result = operand1 / operand2;
    				break;
    			case '&#37;':
    				result = operand1 % operand2;
    				break;
    			default:
    				printf( "Invalid operator specified!" );
    			break;
    
    		}
    
    		//pthread_mutex_unlock( &mutex3 );
    		sem_post( &semaphore3 );
    
    	}//end while
    
    	pthread_exit( NULL );
    }
    
    void *outputFcn( void *id )
    {
    	while( quit == FALSE )
    	{
    		//pthread_mutex_lock( &mutex3 );
    		sem_wait( &semaphore3 );
    
    		printf( "\nResult was %d \n", result );
    
    		//pthread_mutex_unlock( &mutex1 );
    		sem_post( &semaphore1 );
    	}
    
    	pthread_exit( NULL );
    }

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Code:
    while( *input != 'q' || *input != 'Q' )
    Can you think of a possible value of *input that will cause this while loop to stop running? (Hint: Neither 'q' nor 'Q' will do it.)

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Well, technically, it does work, because it compares the first char of the input.
    However, I don't think it's appropriate not a good idea because the user can enter "queen" and it will quit anyway.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Registered User
    Join Date
    Jun 2008
    Posts
    15
    Ya i'm aware of that, that's not a big deal. In fact since it reads expressions anything containing q would be good. So they can even enter a normal expression but if the first letter has a q it will quit. But what about the way i'm shutting down? The segmentation fault's coming from somewhere, so i'm thinking im not closing the threads properly. I want the boolean value quit to let the threads know it's time to shut down. But I guess they have to shut down in an orderly fashion? Any ideas?

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Read it again, guys:
    Code:
    (*input != 'q' || *input != 'Q')
    is ALWAYS TRUE.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I can see you're modifying shared data without synchronization. That's a very bad thing™.
    You mean the "||". That's true.
    Loop while input != 'q' OR input != 'Q'. Doesn't sound right.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    Jun 2008
    Posts
    15
    Ya you're right, I wasn't looking closely before, changed that to an && instead of an ||...fixes the seg fault, but my program doesn't terminate at all. So any suggestions as to how to shut down my threads properly when the 'q' or 'Q' is entered?

    Aside:

    How am I modifying data without synchronization? My threads are constantly executing, my use of semaphores dictates when each thread can modify shared data during their execution. Is that not synchronization?

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    inputFcn does not lock when modifying the shared variables, but the other threads do.
    You must make sure that inputFcn locks when modifying the data!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Jun 2008
    Posts
    15
    Well I tell the input thread to wait until process thread is finished, which isn't finished until output thread is....anyways, I'm still not closer to being able to shut down the threads properly. I can get it done, but it doesn't work 100% right.

  10. #10
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Yeah, you have a mistake in your synchronization.
    The following happens:

    The threads start.
    processFcn and outputFcn go into the while-loop since quit == FALSE.
    They wait for the semaphors with sem_wait(..).
    If q has been entered then inputFcn while loop is not executed.
    So the sem_post(&semaphore2), sem_post(&semaphore1) are not executed. So it freezes there.

    EDIT1: Possible fix
    Code:
            quit = TRUE;
    	sem_post( &semaphore2 );
    at inputFcn

    EDIT2: The above seems to be correct but I get segmentation fault.
    A segmentation fault is caused by
    Code:
    switch ( operator1[0] )
    Consider that somebody just enters q. The following will not be executed:
    Code:
    operator1 = strtok( NULL, " " );
    so operator1[0] would possible give an segmentation fault.

    EDIT3: Fixed the above, didn't need ofc three sem_post(..)
    It works fine for me now. Except as follows:
    As stated above if you just enter q. If you dont no seg fault but you get an "Invalid operator specified", when you quit which you shouldn't.
    Fix both as:
    Code:
    		
      if (operator1 != NULL)
    	  switch ( operator1[0] )            
              {
    		....
    	  }
      operator1 = NULL;
    which works fine.
    You still get seg faults if the user doesn't enter a valid expression though
    Last edited by C_ntua; 06-20-2008 at 06:36 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Dev-C++: Problems with Breakpoint Debugging
    By Thileepan_Bala in forum C Programming
    Replies: 1
    Last Post: 01-17-2008, 10:48 AM
  2. Problem in debugging in Eclipse
    By Bargi in forum Linux Programming
    Replies: 1
    Last Post: 08-21-2007, 09:53 AM
  3. Debugging Dev C++
    By tuurb046 in forum Tech Board
    Replies: 10
    Last Post: 08-16-2007, 12:51 PM
  4. Debugging book recommendation
    By dagans in forum Projects and Job Recruitment
    Replies: 1
    Last Post: 09-13-2005, 07:35 PM
  5. debugging directx apps
    By confuted in forum C++ Programming
    Replies: 1
    Last Post: 08-16-2003, 08:56 AM