C Semaphore strange behavior

I am practicing with concurrency in C and I seem to be running into some problems with semaphores. I am using Xcode 6.3.2 on MacOSX.

Here is a sample program that seems strange: the purpose of the example is to print lines ABCD or BACD

#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <errno.h>

void *thread1(void*);
void *thread2(void*);

sem_t *sem0, *sem1, *sem2;;

int main(int argc, const char * argv[]) {

    pthread_t t1, t2;

    sem0 = sem_open("sem0", O_CREAT, 0600, 2);
    sem1 = sem_open("sem1", O_CREAT, 0600, 0);
    sem2 = sem_open("sem2", O_CREAT, 0600, 0);

    // quick check
    if (sem0 == SEM_FAILED || sem1 == SEM_FAILED || sem2 == SEM_FAILED) {
        printf("Something went wrong\n");
        return 0;
    }

    pthread_create(&t1, NULL, thread1, NULL);
    pthread_create(&t2, NULL, thread2, NULL);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    sem_close(sem0);
    sem_close(sem1);
    sem_close(sem2);

    return 0;
}

void *thread1(void* arg) {
    int n=0;
    while (n<10) {
        sem_wait(sem0);
        printf("A");
        fflush(stdout);
        sem_wait(sem1);
        printf("C");
        fflush(stdout);
        sem_post(sem2);
        n++;
    }
    pthread_exit(NULL);
}

void *thread2(void* arg) {
    int n=0;
    while (n<10) {
        sem_wait(sem0);
        printf("B");
        fflush(stdout);
        sem_post(sem1);
        sem_wait(sem2);
        printf("D\n");
        fflush(stdout);
        sem_post(sem0);
        sem_post(sem0);
        n++;
    }
    pthread_exit(NULL);
}

      

If I did the semaphores correctly, the result would be either ABCD or BACD, but in fact I am getting a whole bunch of strange results.

I'll include some of this output here

ABCD
BAD
CABCD
BAD
CBAD
CBAD
CBAD
CBAD
CBAD
CBAD
C

      

Can anyone help me? thanks in advance

IMPORTANT CHANGE: I downloaded Ubuntu and the code runs smoothly there, no problem at all. So to resume

  • MacOSX 10.10.3 with Xcode 6.3.2 -> Doesn't work as expected
  • Ubuntu 15.04 -> Works Correctly

I do not know why.

+3


source to share


3 answers


Your problem is probably because the output is printf

buffered and shared between threads. You will need to clear the buffer with fflush

before posting to semaphores.



+2


source


There's a typo when you call sem_open()

for sem2

- the name is passed to "sem1"

:

sem1 = sem_open("sem1", O_CREAT, 0600, 0);
sem2 = sem_open("sem1", O_CREAT, 0600, 0);
//               ^^^^

      



Thus, pointers sem1

and sem2

will refer to the same semaphore.

+1


source


Printf accesses one resource, the standard file descriptor. You need to acquire the lock to only allow stdout access one thread at a time. Otherwise, you might end up with alternating text. I'm not sure why you are creating three semaphores, but consider that if you have multiple semaphores blocking the same resource, you have multiple windows open for that resource. If you only close one at a time, then you are not locking the resource at all.

edit : Example. thread 1 locks sem 0, thread 2 is waiting. thread 1 unlocks sem0 and thread 2 can continue. Thread 1 is now blocking sem1. They both write up to standard though. This means that both of them, even obeying your locks, can write to standard output.

Why doesn't this happen sooner, just because of thread conflict.

edit 2 : I think it's John's point that my original explanation doesn't cover your question. I cannot reproduce your output, and I cannot imagine the path to your output. Even with the fflush example mentioned above, I still can't see how this particular line will be formed even using the same buffer with how your semaphores are supposed to work. I can only guess this:

  • Your semaphores are named and you don't destroy them. This means they persist between calls to your program. If you finish your program at the right time, the semaphore values โ€‹โ€‹may be in a state you don't expect (they ignore the sem_open value parameter if the semaphore exists). Perhaps this could lead to an exit.
  • You don't check the return values โ€‹โ€‹of your sem functions, they can return errors. Subsequent function calls on invalid semaphores should return immediately, thereby leaving your printfs a topic of thread only discussion.
0


source







All Articles