Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

set_error() does not get called #156

Closed
Paultok opened this issue Jul 2, 2018 · 4 comments
Closed

set_error() does not get called #156

Paultok opened this issue Jul 2, 2018 · 4 comments

Comments

@Paultok
Copy link

Paultok commented Jul 2, 2018

Hi, the following program has been taken from one of your examples. I modified it to deliberately throw an exception from within await(). Correct me if I am wrong, but in this case the documentation seems to be saying that this would make the library call set_error() at some point in the future, but it does not happen. What am I missing?

// Taken from http://stlab.cc/libraries/concurrency/channel/process/await.html

#include <atomic>
#include <iostream>
#include <thread>
#include <exception>

#include <stlab/concurrency/channel.hpp>
#include <stlab/concurrency/default_executor.hpp>

using namespace std;
using namespace stlab;

struct sum_2
{
    process_state_scheduled _state = await_forever;
    int _counter = 0;
    int _sum = 0;

    void await(int n) {
        throw std::runtime_error{"shouldn't set_error() be called afterwards?"};
        _sum += n;
        ++_counter;
        if (_counter == 2) _state = yield_immediate;
    }

    // http://stlab.cc/libraries/concurrency/channel/process/set_error.html
    void set_error(std::exception_ptr error) { // never called
        cout << "error\n";
    }

    int yield() {
      _state = await_forever;
      auto result = _sum;
      _sum = 0;
      _counter = 0;
      return result;
    }

    auto state() const { return _state; }
};


int main() {
    sender<int> send;
    receiver<int> receive;

    tie(send, receive) = channel<int>(default_executor);

    std::atomic_int r{0};

    auto hold = receive
        | sum_2()
        | [&_r = r](int x) { _r = x; };

    receive.set_ready();

    send(1);
    send(2);

    // Waiting just for illustrational purpose
    while (r == 0) {
        this_thread::sleep_for(std::chrono::milliseconds(1));
    }

    cout << "The sum is " << r.load() << '\n';
}
@FelixPetriconi
Copy link
Member

You are right. I will fix this for the next release.

@Paultok
Copy link
Author

Paultok commented Jul 2, 2018

@FelixPetriconi thank you. Although I did not mention it, it seems I have a similar issue with close() not being called when expected, i.e. when set_error() is NOT defined and an exception is thrown in await(). Let me know if you need an example for this issue too.

@FelixPetriconi
Copy link
Member

@Paultok I have a fix. But it must be called differently than you have thought. set_error is called by the framework on the downstream process, not on the process, where it was thrown. The reason for this is, that any error within await() are expected to be caught within itself. Only errors that happen outside of await() and yield(), e.g. in copy ctor's are intended to be passed to set_error. Since this process has no possibility to handle those in a reasonable way, the errors are passed to the downstream processes. I will see, that the fix is merged soon into the develop branch.

@FelixPetriconi
Copy link
Member

Fixed in 1.3.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants