Skip to content

Conversation

@kallewoof
Copy link
Contributor

@kallewoof kallewoof commented Dec 20, 2016

This PR is the initial part of cleaning up the use of ev*_new/ev*_free.

The relevant, owned types are wrapped in std::unique_ptrs with associated deleters.

Some cases require manually releasing the pointer, such as when an evhttp_request is handed to evhttp_make_request (as its ownership is moved at that point), but otherwise things become mostly automagic.

@kallewoof kallewoof changed the title RAII of libevent stuff using set of wrappers [Refactor] RAII of libevent stuff using set of wrappers Dec 20, 2016
@jonasschnelli
Copy link
Contributor

General concept ACK on a RAII approach (C++ wrapper) for libevent.
I think we should avoid boost::noncopyable and instead use C++11's MyClass& operator=(const MyClass&) = delete; approach.

@kallewoof
Copy link
Contributor Author

@jonasschnelli Fixed.

@laanwj
Copy link
Member

laanwj commented Dec 20, 2016

ACK on making things RAII. Thanks.

I'm not so sure about wrapping the entire interface, though. I'm not sure about others but I'd prefer something thinner.

For example evhttp_set_max_headers_size -> setMaxHeadersSize. This makes it fractionally harder for someone that has learned the libevent APIs to understand the code because the functions are named differently.

(also it adds maintenance overhead as every function of libevent to be used has to be wrapped)

@kallewoof
Copy link
Contributor Author

@laanwj It felt sensible to make the underlying ev* structs private but maybe my intuition was off on that. I'm not entirely convinced that evhttp_set_max_headers_size -> setMaxHeadersSize is a problem, but if you think it is, it may be better to un-private'ify the structs. That would remove the need for friends as well.

@laanwj
Copy link
Member

laanwj commented Dec 20, 2016

It's not a problem but it's one of the little things that I've learned in years developing in open source. If a project makes use of some library which you already know, it's easier to get into it if it is simply using the "lexicon" of that library instead of wrapping everything in custom-named calls.

You could work around this by making the wrapping functions the same as the evhttp calls, e.g. don't do the camel-case thing. But yes I'd prefer not making the inner objects private - make it behave more like a "smart pointer".

Another (less-LoC) alternative to all of this is to define a std::unique_ptr with our own cleanup hook. I've done a similar thing recently in paymentserver.cpp.

struct X509StoreDeleter {
      void operator()(X509_STORE* b) {
          X509_STORE_free(b);
      }
};
std::unique_ptr<X509_STORE, X509StoreDeleter> certStore;

@kallewoof
Copy link
Contributor Author

There is also a slight issue with the evhttp_request which needs to not be freed if a call to evhttp_make_request has been made. By exposing the internal evhttp_request, it's not possible to determine which is the case.

@kallewoof
Copy link
Contributor Author

That (names being same) makes sense. The unique_ptr approach looks very nice, but unsure if it can address the above issue adequately.

@laanwj
Copy link
Member

laanwj commented Dec 20, 2016

There is also a slight issue with the evhttp_request which needs to not be freed if a call to evhttp_make_request has been made. By exposing the internal evhttp_request, it's not possible to determine which is the case.

Couldn't, in that case, the calling code could just .release() the pointer? No need to build that intelligence into the pointer object.

@kallewoof
Copy link
Contributor Author

You mean, explicitly tell the wrapper it no longer owns the object whenever you do evhttp_make_request? I suppose that is doable. I would have loved to not have to risk developers forgetting to do so though.

@laanwj
Copy link
Member

laanwj commented Dec 20, 2016 via email

@kallewoof
Copy link
Contributor Author

Yeah, that makes sense. Thanks for the feedback, will fix!

@kallewoof kallewoof changed the title [Refactor] RAII of libevent stuff using set of wrappers [Refactor] RAII of libevent stuff using unique ptrs with deleters Dec 20, 2016
@kallewoof
Copy link
Contributor Author

kallewoof commented Dec 20, 2016

@laanwj I decided to go with the unique pointer + deleter approach. It became awfully verbose, so I did some macroing.

@laanwj
Copy link
Member

laanwj commented Dec 20, 2016

Nice!
Concept ACK. I think the use of macros is okay in this case, as indeed they all follow the same pattern and it saves a lot of dumb repetition.

Copy link
Contributor

@dcousens dcousens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

concept and light utACK

@kallewoof kallewoof force-pushed the raii-libevents branch 2 times, most recently from 80b1aa0 to f920a9d Compare December 21, 2016 05:11
@laanwj
Copy link
Member

laanwj commented Jan 4, 2017

I tried building this and it fails:

$ make
Making all in src
make[1]: Entering directory '/store2/build/bitcoin/bitcoin/src'
make[2]: Entering directory '/store2/build/bitcoin/bitcoin/src'
...
  CXX      test/test_test_bitcoin-raii_event_tests.o
/.../bitcoin/src/test/raii_event_tests.cpp:5:10: fatal error: 'event2/event.h' file not found
#include <event2/event.h>
         ^~~~~~~~~~~~~~~~
1 error generated.

Perhaps the include directory for libevent headers is not specified for the tests in the Makefile.am?

@kallewoof
Copy link
Contributor Author

kallewoof commented Jan 4, 2017

@laanwj Weird. What does V=1 make give as output?

Edit: Did see that $(EVENT_CFLAGS) was not added to test_test_bitcoin_CPPFLAGS in Makefile.test.include (line 113). I'm confused why my machines (1 Mac OS X and 1 Ubuntu inside VirtualBox) and Travis both find the headers. Does it work if you add that?

@laanwj
Copy link
Member

laanwj commented Jan 4, 2017

Sure:

/usr/bin/ccache /opt/clang40/bin/clang++ -std=c++11 -DHAVE_CONFIG_H -I. -I.../bitcoin/src -I../src/config  -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -I. -I./obj  -pthread -I/usr/include -I.../bitcoin/src/leveldb/include -I.../bitcoin/src/leveldb/helpers/memenv   -I.../bitcoin/src/secp256k1/include -I.../bitcoin/src/univalue/include -I./test/ -DBOOST_TEST_DYN_LINK -Qunused-arguments -ggdb -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS -Wstack-protector -fstack-protector-all -fPIE -g -O2 -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter -Wno-self-assign -Wno-unused-local-typedef -Wno-deprecated-register -MT test/test_test_bitcoin-raii_event_tests.o -MD -MP -MF test/.deps/test_test_bitcoin-raii_event_tests.Tpo -c -o test/test_test_bitcoin-raii_event_tests.o `test -f 'test/raii_event_tests.cpp' || echo '.../bitcoin/src/'`test/raii_event_tests.cpp
.../bitcoin/src/test/raii_event_tests.cpp:5:10: fatal error: 'event2/event.h' file not found
#include <event2/event.h>
         ^~~~~~~~~~~~~~~~
1 error generated.

My configure script looks like:

#!/bin/bash
CLANGPATH=/opt/clang40
$1/configure --with-incompatible-bdb \
    --prefix=/tmp/bitcoin \
    CC="${CLANGPATH}/bin/clang " CXX="${CLANGPATH}/bin/clang++" \
    OBJCXX="${CLANGPATH}/bin/clang++" \
    CPPFLAGS="-ggdb" \
    EVENT_CFLAGS="-I/opt/libevent/include" \
    EVENT_LIBS="-L/opt/libevent/lib -levent" \
    EVENT_PTHREADS_CFLAGS="-I/opt/libevent/include" \
    EVENT_PTHREADS_LIBS="-L/opt/libevent/lib -levent_pthreads" \

@kallewoof
Copy link
Contributor Author

On my system, I have event2 symlinked inside /usr/local/include, which means I don't have to explicitly include it in the g++ call. Adding $(EVENT_CFLAGS) to test_test_bitcoin_CPPFLAGS added explicit references so this should fix it on your end.

@laanwj
Copy link
Member

laanwj commented Jan 4, 2017

Yep, that solved it, thanks! utACK 05a55a6

@laanwj laanwj merged commit 05a55a6 into bitcoin:master Jan 5, 2017
laanwj added a commit that referenced this pull request Jan 5, 2017
… deleters

05a55a6 Added EVENT_CFLAGS to test makefile to explicitly include libevent headers. (Karl-Johan Alm)
280a559 Added some simple tests for the RAII-style events. (Karl-Johan Alm)
7f7f102 Switched bitcoin-cli.cpp to use RAII unique pointers with deleters. (Karl-Johan Alm)
e5534d2 Added std::unique_ptr<> wrappers with deleters for libevent modules. (Karl-Johan Alm)
@kallewoof kallewoof deleted the raii-libevents branch January 5, 2017 10:13
codablock pushed a commit to codablock/dash that referenced this pull request Jan 18, 2018
…rs with deleters

05a55a6 Added EVENT_CFLAGS to test makefile to explicitly include libevent headers. (Karl-Johan Alm)
280a559 Added some simple tests for the RAII-style events. (Karl-Johan Alm)
7f7f102 Switched bitcoin-cli.cpp to use RAII unique pointers with deleters. (Karl-Johan Alm)
e5534d2 Added std::unique_ptr<> wrappers with deleters for libevent modules. (Karl-Johan Alm)
andvgal pushed a commit to energicryptocurrency/gen2-energi that referenced this pull request Jan 6, 2019
…rs with deleters

05a55a6 Added EVENT_CFLAGS to test makefile to explicitly include libevent headers. (Karl-Johan Alm)
280a559 Added some simple tests for the RAII-style events. (Karl-Johan Alm)
7f7f102 Switched bitcoin-cli.cpp to use RAII unique pointers with deleters. (Karl-Johan Alm)
e5534d2 Added std::unique_ptr<> wrappers with deleters for libevent modules. (Karl-Johan Alm)
CryptoCentric pushed a commit to absolute-community/absolute that referenced this pull request Feb 26, 2019
…rs with deleters

05a55a6 Added EVENT_CFLAGS to test makefile to explicitly include libevent headers. (Karl-Johan Alm)
280a559 Added some simple tests for the RAII-style events. (Karl-Johan Alm)
7f7f102 Switched bitcoin-cli.cpp to use RAII unique pointers with deleters. (Karl-Johan Alm)
e5534d2 Added std::unique_ptr<> wrappers with deleters for libevent modules. (Karl-Johan Alm)
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Aug 25, 2021
Summary:
PR description:
> The test suite must always be defined (even when EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED is not defined) so that the test harness doesn't fail due to not being able to find the raii_event_tests test.
>
> This improves upon 95f97f4 actually fixing bitcoin/bitcoin#9493

Context from issue:
> [[bitcoin/bitcoin#9387 | core#9387]] added a new test that uses libevent's event_set_mem_functions which is sometimes not included with libevent. In particular, Gentoo only enables this when libevent is installed with the "debug" option.
> Currently, this causes the build to simply fail on tests

This is a backport of [[bitcoin/bitcoin#16564 | core#16564]]

Test Plan: `ninja check`

Reviewers: #bitcoin_abc, majcosta

Reviewed By: #bitcoin_abc, majcosta

Differential Revision: https://reviews.bitcoinabc.org/D9930
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants