Q:

Multithreaded C Program Not Functioning With Args

I'm struggling with a program in C. It's a multithreaded program which is supposed to have one thread (the reader) read two ints on a line in a file, and print them. The other thread has to add the ints and then print the result.
They are only allowed to communicate with Signals, no Mutexes, Semaphores or Condition Variable are allowed. 
The problem I'm having is that when I run the program with, say, numbers.txt as an argument, nothing appears to happen. I think it stops when trying to open the file, but I'm not really sure.
I'd appreciate any help anyone has to offer, thanks.
EDIT: Ran it with strace, here's what happened: http://pastebin.com/DPf6RPKf
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>

//Struct for numbers and file
typedef struct
{
    int num0, num1;
    FILE *fp;
    pid_t *pid;
    unsigned int seed;

} pair_t;

static void cleanExitReader()
{

    printf("Goodbye from Reader Thread");
}

static void cleanExitCalc()
{
    printf("Goodbye from Calculator Thread");
}

//Reader thread
static void *
readerThread(void *numPair_in)
{
    //Install cleanup handler
    pthread_cleanup_push(cleanExitReader, NULL);
    //Cast numPair_in as the struct
    pair_t * numPair;
    numPair = (pair_t *)numPair_in;
    unsigned int seed;
    //Create sigset and block
    sigset_t blockSigs;
    sigaddset(&blockSigs, SIGUSR1);
    sigaddset(&blockSigs, SIGUSR2);
    pthread_sigmask(SIG_BLOCK, &blockSigs, NULL);

    //Create a sigset for sigwait to listen for.
    sigset_t listenSigs;
    sigemptyset(&listenSigs);
    sigaddset(&listenSigs, SIGUSR1);
    int listenSigs_r;

    //Reading loop
    while(1)
    {
        //Wait for signal from main before starting.
        sigwait(&listenSigs, &listenSigs_r);
        if(fscanf(numPair->fp, "%d %d", &numPair->num0, &numPair->num1) == EOF)
            continue;
        usleep(rand_r(&seed) % 10000);
        printf("%d %d", numPair->num0, numPair->num1);
        kill(*numPair->pid, SIGUSR1);
    }

    pthread_cleanup_pop(1);
}

//Calculator thread
static void *
calcThread(void *numPair_in)
{
    //Install cleanup handler
    pthread_cleanup_push(cleanExitCalc, NULL);
    unsigned int seed;
    //Cast numPair_in as the struct
    pair_t * numPair;
    numPair = (pair_t *)numPair_in;

    //Create sigset and block
    sigset_t blockSigs;
    sigaddset(&blockSigs, SIGUSR1);
    sigaddset(&blockSigs, SIGUSR2);
    pthread_sigmask(SIG_BLOCK, &blockSigs, NULL);

    //Create a sigset for sigwait to wait for.
    sigset_t listenSigs;
    sigemptyset(&listenSigs);
    sigaddset(&listenSigs, SIGUSR2);
    int listenSigs_r;

    //Adding loop
    while(1)
    {
        sigwait(&listenSigs, &listenSigs_r);
        if(feof(numPair->fp))
            continue;
        int i = numPair->num0 + numPair->num1;
        usleep(rand_r(&seed) % 10000);
        printf("%d", i);
        kill(*numPair->pid, SIGUSR2);
    }

    pthread_cleanup_pop(1);
}

//Main
int main (int argc, char *argv[])
{
    //Declare threads, file pointer, pid and struct
    pthread_t r, c;
    FILE *fp;
    pid_t pid;
    pair_t numbers;

    //Exit if no argument given
    if(argc < 2)
    {
        printf("Please enter one file as an argument");
        return 1;
    }

    //Open file
    fp = fopen(argv[1], "r");

    //Exit if fp = null
    if(fp == NULL)
    {
        perror("fopen");
        return 1;
    }

    //Get the process ID of the program
    pid = getpid();

    //Assign values to struct pid and fp
    numbers.pid = &pid;
    numbers.fp = fp;

    //Blocking SIGUSR1 and SIGUSR2
    sigset_t blockSigs;
    sigaddset(&blockSigs, SIGUSR1);
    sigaddset(&blockSigs, SIGUSR2);
    pthread_sigmask(SIG_BLOCK, &blockSigs, NULL);

    //Set up the listening set for SIGUSR1/2
    sigset_t listenSigs;
    sigemptyset(&listenSigs);
    sigaddset(&listenSigs, SIGUSR1);
    sigaddset(&listenSigs, SIGUSR2);
    int listenSigs_r;

    //Create threads here so they inherit sigmasks
    pthread_create(&r, NULL, readerThread, (void *)&numbers);
    pthread_create(&c, NULL, calcThread, (void *)&numbers);

    while(1)
    {
        if(feof(fp))
            break;
        pthread_kill(r, SIGUSR1);
        sigwait(&listenSigs, &listenSigs_r);

        pthread_kill(c, SIGUSR2);
        sigwait(&listenSigs, &listenSigs_r);
    }

    pthread_cancel(r);
    pthread_cancel(c);
    pthread_join(r, NULL);
    pthread_join(c, NULL);

    fclose(fp);
    return 0;
}

A:

You had two main problems:
(1) Mixing kill and pthread_kill. kill will send the signal to the process and it is a random chance which thread waiting on it will get it.  pthread_kill directs it to a specific thread.  So when the reader thread sent a kill sigusr1 to the process both the reader and main were waiting on it and reader would get it every time thus throwing off the sequence.  By changing that to pthread_kill it could be directed to the proper thread.
(2) The eof logic was off. reader would hit eof and immediately loop around and wait, never informing main that things were done.
This is 95% your code so I don't feel guilty giving it to you but you will still need to go through it, look at the changes and clean it up
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>

//Struct for numbers and file
typedef struct
{
    int num0, num1;
    FILE *fp;
    //pid_t *pid;
    pthread_t tid;
    unsigned int seed;
} pair_t;

static void cleanExitReader()
{    
    printf("Goodbye from Reader Thread\n");
}

static void cleanExitCalc()
{
    printf("Goodbye from Calculator Thread\n");
}

//Reader thread
static void *
readerThread(void *numPair_in)
{
    //Install cleanup handler
    pthread_cleanup_push(cleanExitReader, NULL);
    //Cast numPair_in as the struct
    pair_t * numPair;
    numPair = (pair_t *)numPair_in;
    unsigned int seed;

    //Create a sigset for sigwait to listen for.
    sigset_t listenSigs;
    sigemptyset(&listenSigs);
    sigaddset(&listenSigs, SIGUSR1);
    int listenSigs_r;

     //Reading loop
    while(1)
    {
        //Wait for signal from main before starting.
        int result = sigwait(&listenSigs, &listenSigs_r);
        if(result == 0)
            printf("reader sigwait got signal: %d\n", listenSigs_r);

        if(fscanf(numPair->fp, "%d %d", &numPair->num0, &numPair->num1) == EOF)
        {
            pthread_kill(numPair->tid, SIGUSR1);
            continue;
        }
        else
        {
            //usleep(rand_r(&seed) % 10000);
            printf("read values: %d %d\n", numPair->num0, numPair->num1);
            pthread_kill(numPair->tid, SIGUSR1);
        }
    }

    pthread_cleanup_pop(1);
}

//Calculator thread
static void *
calcThread(void *numPair_in)
{
    //Install cleanup handler
    pthread_cleanup_push(cleanExitCalc, NULL);
    unsigned int seed;
    //Cast numPair_in as the struct
    pair_t * numPair;
    numPair = (pair_t *)numPair_in;

    //Create a sigset for sigwait to wait for.
    sigset_t listenSigs;
    sigemptyset(&listenSigs);
    sigaddset(&listenSigs, SIGUSR2);
    int listenSigs_r;

    //Adding loop
    while(1)
    {
        int result = sigwait(&listenSigs, &listenSigs_r);
        if(result == 0)
            printf("calc sigwait got signal: %d\n", listenSigs_r);

        int i = numPair->num0 + numPair->num1;
        //usleep(rand_r(&seed) % 10000);
        printf("result of calc = %d\n", i);
        pthread_kill(numPair->tid, SIGUSR2);
    }

    pthread_cleanup_pop(1);
}

//Main
int main (int argc, char *argv[])
{
    //Declare threads, file pointer, tid and struct
    pthread_t r, c;
    FILE *fp;
    //pid_t pid;
    pthread_t tid;
    pair_t numbers;

    //Exit if no argument given
    if(argc < 2)
    {
        printf("Please enter one file as an argument\n");
        return 1;
    }

    //Open file
    fp = fopen(argv[1], "r");

    //Exit if fp = null
    if(fp == NULL)
    {
        perror("fopen");
        return 1;
    }

    //Get the process ID of the program
    //pid = getpid();
    tid = pthread_self();

    //Assign values to struct tid and fp
    numbers.tid = tid;
    numbers.fp = fp;

    //Blocking SIGUSR1 and SIGUSR2
    sigset_t blockSigs;
    sigaddset(&blockSigs, SIGUSR1);
    sigaddset(&blockSigs, SIGUSR2);
    pthread_sigmask(SIG_BLOCK, &blockSigs, NULL);

    //Create threads here so they inherit sigmasks
    pthread_create(&r, NULL, readerThread, (void *)&numbers);
    pthread_create(&c, NULL, calcThread, (void *)&numbers);

    //Set up the listening set for SIGUSR1/2
    sigset_t listenSigs;
    sigemptyset(&listenSigs);
    sigaddset(&listenSigs, SIGUSR1);
    sigaddset(&listenSigs, SIGUSR2);
    int listenSigs_r;

    while(1)
    {
        if(feof(fp))
            break;

        pthread_kill(r, SIGUSR1);
        int result = sigwait(&listenSigs, &listenSigs_r);
        if(result == 0)
            printf("main 1 sigwait got signal: %d\n", listenSigs_r);

        pthread_kill(c, SIGUSR2);
        sigwait(&listenSigs, &listenSigs_r);
        if(result == 0)
            printf("main 2 sigwait got signal: %d\n", listenSigs_r);

        printf("\n\n"); //easier to read

    }

    pthread_cancel(r);
    pthread_cancel(c);
    pthread_join(r, NULL);
    pthread_join(c, NULL);

    fclose(fp);
    return 0;
}

