Commit 546ea7b1 authored by Dominik Charousset's avatar Dominik Charousset

Merge pull request #1163

parents 81c00c70 1c96d267
...@@ -5,6 +5,7 @@ set -e ...@@ -5,6 +5,7 @@ set -e
# This script expects the CAF source tree under 'sources', builds in 'build' and # This script expects the CAF source tree under 'sources', builds in 'build' and
# installs to 'bundle'. Additionally, the script expects the CMake pre-load # installs to 'bundle'. Additionally, the script expects the CMake pre-load
# script 'cmake-init.txt' in the current working directorys. # script 'cmake-init.txt' in the current working directorys.
BaseDir="$PWD"
InitFile="$PWD/cmake-init.txt" InitFile="$PWD/cmake-init.txt"
SourceDir="$PWD/sources" SourceDir="$PWD/sources"
BuildDir="$PWD/build" BuildDir="$PWD/build"
...@@ -23,6 +24,28 @@ else ...@@ -23,6 +24,28 @@ else
exit 1 exit 1
fi fi
LeakSanCheck="
#include <cstdlib>
int main() {
int* ptr = new int(EXIT_SUCCESS);
return *ptr;
}
"
# Check that LeakSanitizer works if configured for this build.
if [ "${CAF_CHECK_LEAKS}" == "ON" ]; then
mkdir -p "$BaseDir/LeakCheck"
cd "$BaseDir/LeakCheck"
echo "${LeakSanCheck}" > check.cpp
c++ check.cpp -o check -fsanitize=address -fno-omit-frame-pointer
out=`./check 2>&1 | grep -o LeakSanitizer`
if [ "$out" != "LeakSanitizer" ]; then
echo "unable to detected memory leaks on this platform!"
return 1
fi
cd "$BaseDir"
fi
# Make sure all directories exist, then enter build directory. # Make sure all directories exist, then enter build directory.
mkdir -p "$BuildDir" mkdir -p "$BuildDir"
cd "$BuildDir" cd "$BuildDir"
...@@ -34,4 +57,4 @@ if [ -z "$CAF_NUM_CORES" ]; then ...@@ -34,4 +57,4 @@ if [ -z "$CAF_NUM_CORES" ]; then
else else
$CMakeCommand --build . --target install -- -j $CAF_NUM_CORES $CMakeCommand --build . --target install -- -j $CAF_NUM_CORES
fi fi
$CTestCommand $CTestCommand --output-on-failure
...@@ -46,6 +46,8 @@ is based on [Keep a Changelog](https://keepachangelog.com). ...@@ -46,6 +46,8 @@ is based on [Keep a Changelog](https://keepachangelog.com).
to reject log messages immediately (before enqueueing it to the logger's to reject log messages immediately (before enqueueing it to the logger's
queue) and then applies the filters individually when generating file or queue) and then applies the filters individually when generating file or
console output. console output.
- Fix memory leaks when deserializing URIs and when detaching the content of
messages (#1160).
## [0.18.0-rc.1] - 2020-09-09 ## [0.18.0-rc.1] - 2020-09-09
......
...@@ -31,13 +31,11 @@ config = [ ...@@ -31,13 +31,11 @@ config = [
numCores: 4, numCores: 4,
tags: ['docker'], tags: ['docker'],
builds: ['debug', 'release'], builds: ['debug', 'release'],
extraDebugFlags: ['CAF_SANITIZERS:STRING=address,undefined'],
]], ]],
['centos-8', [ ['centos-8', [
numCores: 4, numCores: 4,
tags: ['docker'], tags: ['docker'],
builds: ['debug', 'release'], builds: ['debug', 'release'],
extraDebugFlags: ['CAF_SANITIZERS:STRING=address,undefined'],
]], ]],
['debian-9', [ ['debian-9', [
numCores: 4, numCores: 4,
...@@ -73,6 +71,7 @@ config = [ ...@@ -73,6 +71,7 @@ config = [
numCores: 4, numCores: 4,
tags: ['docker'], tags: ['docker'],
builds: ['debug', 'release'], builds: ['debug', 'release'],
extraDebugFlags: ['CAF_SANITIZERS:STRING=address'],
]], ]],
// One extra debug build with exceptions disabled. // One extra debug build with exceptions disabled.
['centos-7', [ ['centos-7', [
...@@ -119,6 +118,10 @@ config = [ ...@@ -119,6 +118,10 @@ config = [
], ],
// Platform-specific environment settings. // Platform-specific environment settings.
buildEnvironments: [ buildEnvironments: [
'fedora-32 && debug': [
'CAF_CHECK_LEAKS=ON',
'ASAN_OPTIONS=detect_leaks=1',
],
nop: [], // Dummy value for getting the proper types. nop: [], // Dummy value for getting the proper types.
], ],
// Default CMake flags by build type. // Default CMake flags by build type.
...@@ -164,7 +167,7 @@ pipeline { ...@@ -164,7 +167,7 @@ pipeline {
environment { environment {
PrettyJobBaseName = env.JOB_BASE_NAME.replace('%2F', '/') PrettyJobBaseName = env.JOB_BASE_NAME.replace('%2F', '/')
PrettyJobName = "CAF/$PrettyJobBaseName #${env.BUILD_NUMBER}" PrettyJobName = "CAF/$PrettyJobBaseName #${env.BUILD_NUMBER}"
ASAN_OPTIONS = 'detect_leaks=0' ASAN_OPTIONS = 'detect_leaks=1'
} }
stages { stages {
stage('Checkout') { stage('Checkout') {
......
...@@ -32,7 +32,7 @@ public: ...@@ -32,7 +32,7 @@ public:
// nop // nop
} }
explicit typed_message_view(message& msg) : ptr_(&msg.data()) { explicit typed_message_view(message& msg) : ptr_(msg.ptr()) {
// nop // nop
} }
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "caf/intrusive_cow_ptr.hpp" #include "caf/intrusive_cow_ptr.hpp"
#include "caf/intrusive_ptr.hpp" #include "caf/intrusive_ptr.hpp"
#include "caf/ip_address.hpp" #include "caf/ip_address.hpp"
#include "caf/make_counted.hpp"
#include "caf/string_view.hpp" #include "caf/string_view.hpp"
#include "caf/variant.hpp" #include "caf/variant.hpp"
...@@ -274,7 +275,7 @@ struct inspector_access<uri> : inspector_access_base<uri> { ...@@ -274,7 +275,7 @@ struct inspector_access<uri> : inspector_access_base<uri> {
} else { } else {
if constexpr (Inspector::is_loading) if constexpr (Inspector::is_loading)
if (!x.impl_->unique()) if (!x.impl_->unique())
x.impl_.reset(new uri::impl_type); x.impl_.reset(new uri::impl_type, false);
return inspect(f, *x.impl_); return inspect(f, *x.impl_);
} }
} }
...@@ -291,7 +292,7 @@ struct inspector_access<uri> : inspector_access_base<uri> { ...@@ -291,7 +292,7 @@ struct inspector_access<uri> : inspector_access_base<uri> {
} else { } else {
if constexpr (Inspector::is_loading) if constexpr (Inspector::is_loading)
if (!x.impl_->unique()) if (!x.impl_->unique())
x.impl_.reset(new uri::impl_type); x.impl_.reset(new uri::impl_type, false);
return inspect(f, *x.impl_); return inspect(f, *x.impl_);
} }
} }
......
...@@ -120,15 +120,17 @@ void group_tunnel::stop() { ...@@ -120,15 +120,17 @@ void group_tunnel::stop() {
CAF_LOG_TRACE(""); CAF_LOG_TRACE("");
CAF_LOG_DEBUG("stop group tunnel:" << CAF_ARG2("module", module().name()) CAF_LOG_DEBUG("stop group tunnel:" << CAF_ARG2("module", module().name())
<< CAF_ARG2("identifier", identifier_)); << CAF_ARG2("identifier", identifier_));
auto hdl = actor{}; auto worker_hdl = actor{};
auto intermediary_hdl = actor{};
auto subs = subscriber_set{}; auto subs = subscriber_set{};
auto cache = cached_message_list{}; auto cache = cached_message_list{};
auto stopped = critical_section([this, &hdl, &subs, &cache] { auto stopped = critical_section([&, this] {
using std::swap; using std::swap;
if (!stopped_) { if (!stopped_) {
stopped_ = true; stopped_ = true;
swap(subs, subscribers_); swap(subs, subscribers_);
swap(hdl, worker_); swap(worker_hdl, worker_);
swap(intermediary_hdl, intermediary_);
swap(cache, cached_messages_); swap(cache, cached_messages_);
return true; return true;
} else { } else {
...@@ -136,7 +138,7 @@ void group_tunnel::stop() { ...@@ -136,7 +138,7 @@ void group_tunnel::stop() {
} }
}); });
if (stopped) { if (stopped) {
anon_send_exit(hdl, exit_reason::user_shutdown); anon_send_exit(worker_hdl, exit_reason::user_shutdown);
if (!subs.empty()) { if (!subs.empty()) {
auto bye = make_message(group_down_msg{group{this}}); auto bye = make_message(group_down_msg{group{this}});
for (auto& sub : subs) for (auto& sub : subs)
......
...@@ -163,7 +163,7 @@ expected<group> local_group_module::get(const std::string& group_name) { ...@@ -163,7 +163,7 @@ expected<group> local_group_module::get(const std::string& group_name) {
auto ptr = make_counted<impl>(this, group_name); auto ptr = make_counted<impl>(this, group_name);
ptr->intermediary_ = system().spawn<intermediary_actor, hidden>(ptr); ptr->intermediary_ = system().spawn<intermediary_actor, hidden>(ptr);
instances_.emplace(group_name, ptr); instances_.emplace(group_name, ptr);
return group{ptr.release()}; return group{std::move(ptr)};
} }
} }
......
...@@ -69,6 +69,7 @@ message_data* message_data::copy() const { ...@@ -69,6 +69,7 @@ message_data* message_data::copy() const {
auto& meta = gmos[id]; auto& meta = gmos[id];
// TODO: exception handling. // TODO: exception handling.
meta.copy_construct(dst, src); meta.copy_construct(dst, src);
++ptr->constructed_elements_;
src += meta.padded_size; src += meta.padded_size;
dst += meta.padded_size; dst += meta.padded_size;
} }
......
...@@ -83,8 +83,9 @@ struct testee_state { ...@@ -83,8 +83,9 @@ struct testee_state {
behavior testee_impl(stateful_actor<testee_state>* self) { behavior testee_impl(stateful_actor<testee_state>* self) {
return { return {
[=](put_atom, int x) { self->state.x = x; }, [self](put_atom, int x) { self->state.x = x; },
[=](get_atom) { return self->state.x; }, [self](get_atom) { return self->state.x; },
[self](const group_down_msg&) { self->quit(); },
}; };
} }
...@@ -103,9 +104,11 @@ struct fixture : test_coordinator_fixture<> { ...@@ -103,9 +104,11 @@ struct fixture : test_coordinator_fixture<> {
// Groups keep their subscribers alive (on purpose). Since we don't want to // Groups keep their subscribers alive (on purpose). Since we don't want to
// manually kill all our testee actors, we simply force the group modules to // manually kill all our testee actors, we simply force the group modules to
// stop here. // stop here.
uut->stop();
for (auto& kvp : uut->instances) for (auto& kvp : uut->instances)
kvp.second->stop(); kvp.second->stop();
sys.groups().get_module("local")->stop(); sys.groups().get_module("local")->stop();
run();
} }
void make_unconnected() { void make_unconnected() {
......
...@@ -61,6 +61,24 @@ CAF_TEST(messages allow index - based access) { ...@@ -61,6 +61,24 @@ CAF_TEST(messages allow index - based access) {
CAF_CHECK_EQUAL(msg.cdata().get_reference_count(), 1u); CAF_CHECK_EQUAL(msg.cdata().get_reference_count(), 1u);
} }
CAF_TEST(message detach their content on mutating access) {
CAF_MESSAGE("Given to messages pointing to the same content.");
auto msg1 = make_message("one", uint32_t{1});
auto msg2 = msg1;
CAF_CHECK_EQUAL(msg1.cdata().get_reference_count(), 2u);
CAF_CHECK_EQUAL(msg1.cptr(), msg2.cptr());
CAF_MESSAGE("When calling a non-const member function of message.");
msg1.ptr();
CAF_MESSAGE("Then the messages point to separate contents but remain equal.");
CAF_CHECK_NOT_EQUAL(msg1.cptr(), msg2.cptr());
CAF_CHECK_EQUAL(msg1.cdata().get_reference_count(), 1u);
CAF_CHECK_EQUAL(msg2.cdata().get_reference_count(), 1u);
CAF_CHECK(msg1.match_elements<std::string, uint32_t>());
CAF_CHECK(msg2.match_elements<std::string, uint32_t>());
CAF_CHECK_EQUAL(msg1.get_as<std::string>(0), msg2.get_as<std::string>(0));
CAF_CHECK_EQUAL(msg1.get_as<uint32_t>(1), msg2.get_as<uint32_t>(1));
}
CAF_TEST(compare_custom_types) { CAF_TEST(compare_custom_types) {
s2 tmp; s2 tmp;
tmp.value[0][1] = 100; tmp.value[0][1] = 100;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment