Legion
Legion

Reputation: 836

Why is this int being updated?

On my school project (a multi-threaded shell) I am trying to add some debug statements in the code. I ran into an interesting situation and would like to know why it is happening.

int signals(void)
{
    if (tcb[curTask].signal)
    {
        int beforeSignal = tcb[curTask].signal;
        if (tcb[curTask].signal & mySIGINT)
        {
            tcb[curTask].signal &= ~mySIGINT; // clears the mySIGINT from the signals
            (*tcb[curTask].sigIntHandler)();
        }
        if (tcb[curTask].signal & mySIGCONT)
        {
            tcb[curTask].signal &= ~mySIGCONT; // clears the mySIGCONT from the signals
            (*tcb[curTask].sigContHandler)();
        }
        if (tcb[curTask].signal & mySIGTERM)
        {
            tcb[curTask].signal &= ~mySIGTERM; // clears the mySIGTERM from the signals
            (*tcb[curTask].sigTermHandler)();
        }
        if (tcb[curTask].signal & mySIGTSTP)
        {
             tcb[curTask].signal &= ~mySIGTSTP; // clears the mySIGTSTP from the signals
            (*tcb[curTask].sigTstpHandler)();
        }
        if (DEBUG) {
            printf("\nSignals:\n\tBefore: %s\n\tAfter: %s",byte_to_binary(beforeSignal), byte_to_binary(tcb[curTask].signal));
        }
    }
    return 0;
}

TCB is a struct:

typedef struct                          // task control block
{
    char* name;                         // task name
    int (*task)(int,char**);        // task address
    int state;                          // task state
    int priority;                       // task priority (project 2)
    int argc;                           // task argument count (project 1)
    char** argv;                        // task argument pointers (project 1)
    int signal;                         // task signals (project 1)
    void (*sigContHandler)(void);   // task mySIGCONT handler
    void (*sigIntHandler)(void);    // task mySIGINT handler
    void (*sigKillHandler)(void);   // task mySIGKILL handler
    void (*sigTermHandler)(void);   // task mySIGTERM handler
    void (*sigTstpHandler)(void);   // task mySIGTSTP handler
    TID parent;                         // task parent
    int RPT;                                // task root page table (project 5)
    int cdir;                           // task directory (project 6)
    Semaphore *event;                   // blocked task semaphore
    void* stack;                        // task stack
    jmp_buf context;                    // task context pointer
} TCB;

and byte_to_binary converts the int to a binary string.

const char *byte_to_binary(int x)
{
    static char b[9];
    b[0] = '\0';

    int z;
    for (z = 128; z > 0; z >>= 1)
    {
        strcat(b, ((x & z) == z) ? "1" : "0");
    }

    return b;
}

When the debug statement prints it looks like this:

Signals:
    Before: 000000000
    After: 000000000

Printing the signal where the beforeSignal int is assigned and after the conditial/masking blocks results in:

Signals:
    Before: 00001000
    After: 00000000

So it appears that the beforeSignal is being updated by the masking operations in the conditionals. I thought that integers were always passed by value so I don't get why the int is being changed from its initial value. I am sure there is a simple method to get a "copy" of the int that won't mirror the original value and I would appreciate knowing it.

Upvotes: 0

Views: 73

Answers (1)

Michael Burr
Michael Burr

Reputation: 340198

The problem is that you place the result of the byte_to_binary() function in a static buffer. The statement where printf() is called actually makes both calls to byte_to_binary() before transferring control to printf(). So printf() just displays the same buffer twice.

You'll need to do something like have byte_to_binary() return a string that's allocated dynamically then free it later (in which case you can't easily use it in a call to printf() without a memory leak), or you'll need to change the interface so that the output buffer is passed into byte_to_binary(). Just have byte_to_binary() return the pointer that is passed in and you can call it from printf() like you're doing now.

Upvotes: 3

Related Questions