Giter Club home page Giter Club logo

Comments (6)

tylertreat avatar tylertreat commented on September 16, 2024

You're welcome to make a pull request, otherwise I will work through these changes myself.

This looks like it works, which is nice to be able to remove blocking pipe. I noticed you're using pthread_yield() in the tests. This doesn't appear to be defined in my pthread.h. How does it differ from sched_yield()?

from chan.

je-so avatar je-so commented on September 16, 2024

There is no difference except for pthread_yield not being POSIX.

from chan.

tylertreat avatar tylertreat commented on September 16, 2024

I have a PR (#14) open with the proposed changes for removing blocking_pipe_t, but I'm holding off on merging it right now since the following unit test appears to be failing sporadically:

void test_chan_select_send()
{
    chan_t* chan1 = chan_init(0);
    chan_t* chan2 = chan_init(1);
    chan_t* chans[2] = {chan1, chan2};
    void* msg[] = {"foo", "bar"};

    switch(chan_select(NULL, 0, NULL, chans, 2, msg))
    {
        case 0:
            chan_dispose(chan1);
            chan_dispose(chan2);
            fprintf(stderr, "Sent on wrong channel");
            exit(1);
        case 1:
            break;
        default:
            chan_dispose(chan1);
            chan_dispose(chan2);
            fprintf(stderr, "Sent on no channels");
            exit(1);
    }

    void* recv;
    chan_recv(chan2, &recv);
    if (strcmp(recv, "bar") != 0)
    {
        chan_dispose(chan1);
        chan_dispose(chan2);
        fprintf(stderr, "Messages are not equal");
        exit(1);
    }

    chan_send(chan2, "foo");

    pthread_t th;
    pthread_create(&th, NULL, receiver, chan1);
    sleep(1);

    switch(chan_select(NULL, 0, NULL, chans, 2, msg))
    {
        case 0:
            break;
        case 1:
            chan_dispose(chan1);
            chan_dispose(chan2);
            fprintf(stderr, "Sent on wrong channel");
            exit(1);
        default:
            chan_dispose(chan1);
            chan_dispose(chan2);
            fprintf(stderr, "Sent on no channels");
            exit(1);
    }

    switch(chan_select(NULL, 0, NULL, &chan1, 1, msg[0]))
    {
        case 0:
            chan_dispose(chan1);
            chan_dispose(chan2);
            fprintf(stderr, "Sent on channel");
            exit(1);
        default:
            break;
    }

    chan_dispose(chan1);
    chan_dispose(chan2);
    pass();
}

The failure is almost certainly due to the race condition here:

pthread_t th;
pthread_create(&th, NULL, receiver, chan1);
sleep(1);
...

We're hitting the chan_select before the recv is executed. Issue is unrelated to the removal of the blocking pipe.

from chan.

tylertreat avatar tylertreat commented on September 16, 2024

I'm attempting to replace all instances of sleep(1) with the following (or its writer equivalent):

void wait_for_reader(chan_t* chan)
{
    for (;;)
    {
        pthread_mutex_lock(&chan->m_mu);
        int send = chan->r_waiting > 0;
        pthread_mutex_unlock(&chan->m_mu);
        if (send) break;
        sched_yield();
    }
}

For some reason, this occasionally results in an infinite loop. It isn't entirely clear to me why this would be happening since wait_for_reader is being called on an unbuffered channel before a call to send, so r_waiting should eventually be incremented to 1 and the reader thread blocked.

from chan.

je-so avatar je-so commented on September 16, 2024

Try adding pthread_join(&th, NULL); in every test where you create a thread.
I sometimes have memory corruption errors due to started threads hanging around.

For example

pthread_create(&th, NULL, sender, chan);
assert_true(...);
...
chan_dispose(chan);

There is a race if chan is disposed before sender is run (memory corruption possible).

Also:

I've replaced sleep(1); with wait_for_writer(chan1); in test_chan_select_recv()
cause sometimes the whole test aborted.
The reason: In case of an error chan_dispose is called without a preceding pthread_join.
This produces a memory corruption if the created thread has not been run first.

from chan.

tylertreat avatar tylertreat commented on September 16, 2024

Yep—that fixed it, thanks!

from chan.

Related Issues (16)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.