Commit 21a508bb authored by Kenton Varda's avatar Kenton Varda

Add valgrind pass to test script. Fix valgrind errors.

parent f66ca5e8
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "array.h" #include "array.h"
#include "exception.h"
namespace kj { namespace kj {
...@@ -62,38 +63,43 @@ void NullArrayDisposer::disposeImpl( ...@@ -62,38 +63,43 @@ void NullArrayDisposer::disposeImpl(
namespace _ { // private namespace _ { // private
struct AutoDeleter {
void* ptr;
inline void* release() { void* result = ptr; ptr = nullptr; return result; }
inline AutoDeleter(void* ptr): ptr(ptr) {}
inline ~AutoDeleter() { operator delete(ptr); }
};
void* HeapArrayDisposer::allocateImpl(size_t elementSize, size_t elementCount, size_t capacity, void* HeapArrayDisposer::allocateImpl(size_t elementSize, size_t elementCount, size_t capacity,
void (*constructElement)(void*), void (*constructElement)(void*),
void (*destroyElement)(void*)) { void (*destroyElement)(void*)) {
void* result = operator new(elementSize * capacity); AutoDeleter result(operator new(elementSize * capacity));
if (constructElement == nullptr) { if (constructElement == nullptr) {
// Nothing to do. // Nothing to do.
} else if (destroyElement == nullptr) { } else if (destroyElement == nullptr) {
byte* pos = reinterpret_cast<byte*>(result); byte* pos = reinterpret_cast<byte*>(result.ptr);
while (elementCount > 0) { while (elementCount > 0) {
constructElement(pos); constructElement(pos);
pos += elementSize; pos += elementSize;
--elementCount; --elementCount;
} }
} else { } else {
ExceptionSafeArrayUtil guard(result, elementSize, 0, destroyElement); ExceptionSafeArrayUtil guard(result.ptr, elementSize, 0, destroyElement);
guard.construct(elementCount, constructElement); guard.construct(elementCount, constructElement);
guard.release(); guard.release();
} }
return result; return result.release();
} }
void HeapArrayDisposer::disposeImpl( void HeapArrayDisposer::disposeImpl(
void* firstElement, size_t elementSize, size_t elementCount, size_t capacity, void* firstElement, size_t elementSize, size_t elementCount, size_t capacity,
void (*destroyElement)(void*)) const { void (*destroyElement)(void*)) const {
// Note that capacity is ignored since operator delete() doesn't care about it. // Note that capacity is ignored since operator delete() doesn't care about it.
AutoDeleter deleter(firstElement);
if (destroyElement == nullptr) { if (destroyElement != nullptr) {
operator delete(firstElement);
} else {
KJ_DEFER(operator delete(firstElement));
ExceptionSafeArrayUtil guard(firstElement, elementSize, elementCount, destroyElement); ExceptionSafeArrayUtil guard(firstElement, elementSize, elementCount, destroyElement);
guard.destroyAll(); guard.destroyAll();
} }
......
...@@ -95,6 +95,40 @@ TEST(Exception, ExceptionCallbackMustBeOnStack) { ...@@ -95,6 +95,40 @@ TEST(Exception, ExceptionCallbackMustBeOnStack) {
#endif #endif
} }
#if !KJ_NO_EXCEPTIONS
TEST(Exception, ScopeSuccessFail) {
bool success = false;
bool failure = false;
{
KJ_ON_SCOPE_SUCCESS(success = true);
KJ_ON_SCOPE_FAILURE(failure = true);
EXPECT_FALSE(success);
EXPECT_FALSE(failure);
}
EXPECT_TRUE(success);
EXPECT_FALSE(failure);
success = false;
failure = false;
try {
KJ_ON_SCOPE_SUCCESS(success = true);
KJ_ON_SCOPE_FAILURE(failure = true);
EXPECT_FALSE(success);
EXPECT_FALSE(failure);
throw 1;
} catch (int) {}
EXPECT_FALSE(success);
EXPECT_TRUE(failure);
}
#endif
} // namespace } // namespace
} // namespace _ (private) } // namespace _ (private)
} // namespace kj } // namespace kj
...@@ -262,6 +262,16 @@ void UnwindDetector::catchExceptionsIfUnwinding(Func&& func) const { ...@@ -262,6 +262,16 @@ void UnwindDetector::catchExceptionsIfUnwinding(Func&& func) const {
} }
} }
#define KJ_ON_SCOPE_SUCCESS(code) \
::kj::UnwindDetector KJ_UNIQUE_NAME(_kjUnwindDetector); \
KJ_DEFER(if (!KJ_UNIQUE_NAME(_kjUnwindDetector).isUnwinding()) { code; })
// Runs `code` if the current scope is exited normally (not due to an exception).
#define KJ_ON_SCOPE_FAILURE(code) \
::kj::UnwindDetector KJ_UNIQUE_NAME(_kjUnwindDetector); \
KJ_DEFER(if (KJ_UNIQUE_NAME(_kjUnwindDetector).isUnwinding()) { code; })
// Runs `code` if the current scope is exited due to an exception.
} // namespace kj } // namespace kj
#endif // KJ_EXCEPTION_H_ #endif // KJ_EXCEPTION_H_
...@@ -295,11 +295,11 @@ void FdOutputStream::write(ArrayPtr<const ArrayPtr<const byte>> pieces) { ...@@ -295,11 +295,11 @@ void FdOutputStream::write(ArrayPtr<const ArrayPtr<const byte>> pieces) {
} }
while (current < iov.end()) { while (current < iov.end()) {
ssize_t n; ssize_t n = 0;
KJ_SYSCALL(n = ::writev(fd, current, iov.end() - current), fd); KJ_SYSCALL(n = ::writev(fd, current, iov.end() - current), fd);
KJ_ASSERT(n > 0, "writev() returned zero."); KJ_ASSERT(n > 0, "writev() returned zero.");
while (static_cast<size_t>(n) >= current->iov_len) { while (n > 0 && static_cast<size_t>(n) >= current->iov_len) {
n -= current->iov_len; n -= current->iov_len;
++current; ++current;
} }
......
...@@ -289,6 +289,18 @@ doit make distclean ...@@ -289,6 +289,18 @@ doit make distclean
doit ./configure --disable-shared CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions" doit ./configure --disable-shared CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions"
doit make -j6 check doit make -j6 check
if which valgrind > /dev/null; then
echo "========================================================================="
echo "Testing with valgrind"
echo "========================================================================="
doit ./configure --disable-shared CXXFLAGS="-g"
doit make -j6
doit make -j6 capnp-test
doin valgrind --leak-check=full --track-fds=yes --error-exitcode=1 capnp-test
doit make distclean
fi
doit make maintainer-clean doit make maintainer-clean
rm -rf "$STAGING" rm -rf "$STAGING"
......
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