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

Add ASAN support and fix memleaks (main) #291

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ set(IRODS_PACKAGE_REVISION "0")

include(IrodsCXXCompiler)
set(CMAKE_CXX_STANDARD ${IRODS_CXX_STANDARD})
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-Wl,--enable-new-dtags -Wl,--as-needed -Wl,-z,defs")
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-Wl,--enable-new-dtags -Wl,--as-needed")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE_INIT "-Wl,--gc-sections -Wl,-z,combreloc")
include(IrodsRunpathDefaults)

Expand Down Expand Up @@ -38,6 +38,34 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fpermissive>)
endif()

option(IRODS_ENABLE_ADDRESS_SANITIZER "Enables detection of memory leaks and other features provided by Address Sanitizer." OFF)
if (IRODS_ENABLE_ADDRESS_SANITIZER)
# Make sure the correct llvm-symbolizer binary is available to Address Sanitizer. This binary
# allows debug symbols to be reported appropriately. There are two ways to do this:
#
# export PATH=/opt/irods-externals/clang13.0.1-0/bin:$PATH
#
# - or -
#
# export ASAN_SYMBOLIZER_PATH=/opt/irods-externals/clang13.0.1-0/bin/llvm-symbolizer
#
# detect_container_overflow is disabled to guard against false positives which occur when
# parts of the binary are compiled with ASAN and other parts are not.
add_compile_definitions(IRODS_ADDRESS_SANITIZER_DEFAULT_OPTIONS="log_path=/tmp/irods_storage_tiering_asan_output:detect_container_overflow=0")
add_compile_options(
-fsanitize=address
-fno-omit-frame-pointer
-fno-optimize-sibling-calls
-O1)
add_link_options(
-fsanitize=address
-fno-omit-frame-pointer
-fno-optimize-sibling-calls
-O1)
else()
set(CMAKE_MODULE_LINKER_FLAGS_INIT "${CMAKE_MODULE_LINKER_FLAGS_INIT} -Wl,-z,defs")
endif()

if (NOT DEFINED THREADS_PREFER_PTHREAD_FLAG)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
endif()
Expand Down
38 changes: 22 additions & 16 deletions irods_consortium_continuous_integration_build_hook.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
from __future__ import print_function

import argparse
import glob
import multiprocessing
import optparse
import os
import tempfile

import irods_python_ci_utilities


def add_cmake_to_front_of_path():
cmake_path = '/opt/irods-externals/cmake3.21.4-0/bin'
os.environ['PATH'] = os.pathsep.join([cmake_path, os.environ['PATH']])
Expand Down Expand Up @@ -61,25 +58,34 @@ def copy_output_packages(build_directory, output_root_directory):
irods_python_ci_utilities.append_os_specific_directory(output_root_directory),
lambda s:s.endswith(irods_python_ci_utilities.get_package_suffix()))

def main(build_directory, output_root_directory, irods_packages_root_directory, externals_directory):
def main(build_directory, output_root_directory, irods_packages_root_directory, externals_directory, debug_build=False, enable_asan=False):
install_building_dependencies(externals_directory)
if irods_packages_root_directory:
irods_python_ci_utilities.install_irods_dev_and_runtime_packages(irods_packages_root_directory)
build_directory = os.path.abspath(build_directory or tempfile.mkdtemp(prefix='irods_storage_tiering_plugin_build_directory'))
irods_python_ci_utilities.subprocess_get_output(['cmake', os.path.dirname(os.path.realpath(__file__))], check_rc=True, cwd=build_directory)
build_type = "Debug" if debug_build else "Release"
cmake_options = [f"-DCMAKE_BUILD_TYPE={build_type}"]
if enable_asan:
cmake_options.append("-DIRODS_ENABLE_ADDRESS_SANITIZER=YES")
cmake_command = ['cmake', os.path.dirname(os.path.realpath(__file__))] + cmake_options
irods_python_ci_utilities.subprocess_get_output(cmake_command, check_rc=True, cwd=build_directory)
irods_python_ci_utilities.subprocess_get_output(['make', '-j', str(multiprocessing.cpu_count()), 'package'], check_rc=True, cwd=build_directory)
if output_root_directory:
copy_output_packages(build_directory, output_root_directory)

if __name__ == '__main__':
parser = optparse.OptionParser()
parser.add_option('--build_directory')
parser.add_option('--output_root_directory')
parser.add_option('--irods_packages_root_directory')
parser.add_option('--externals_packages_directory')
options, _ = parser.parse_args()
parser = argparse.ArgumentParser(description='Build unified storage tiering plugin.')
parser.add_argument('--build_directory')
parser.add_argument('--output_root_directory')
parser.add_argument('--irods_packages_root_directory')
parser.add_argument('--externals_packages_directory')
parser.add_argument('--debug_build', action='store_true')
parser.add_argument("--enable_address_sanitizer", dest="enable_asan", action="store_true")
args = parser.parse_args()

main(options.build_directory,
options.output_root_directory,
options.irods_packages_root_directory,
options.externals_packages_directory)
main(args.build_directory,
args.output_root_directory,
args.irods_packages_root_directory,
args.externals_packages_directory,
args.debug_build,
args.enable_asan)
4 changes: 4 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "irods/private/storage_tiering/exec_as_user.hpp"

#include <irods/filesystem.hpp>
#include <irods/irods_at_scope_exit.hpp>
#include <irods/irods_query.hpp>

#undef LIST
Expand Down Expand Up @@ -118,6 +119,7 @@ namespace {
}

dataObjInp_t data_obj_inp{};
const auto free_cond_input = irods::at_scope_exit{[&data_obj_inp] { clearKeyVal(&data_obj_inp.condInput); }};
rstrcpy(data_obj_inp.objPath, _object_path.c_str(), MAX_NAME_LEN);
data_obj_inp.createMode = getDefFileMode();
addKeyVal(&data_obj_inp.condInput, RESC_NAME_KW, _source_resource.c_str());
Expand Down Expand Up @@ -149,6 +151,7 @@ namespace {
}

dataObjInp_t obj_inp{};
const auto free_cond_input = irods::at_scope_exit{[&obj_inp] { clearKeyVal(&obj_inp.condInput); }};
rstrcpy(
obj_inp.objPath,
_object_path.c_str(),
Expand Down Expand Up @@ -192,6 +195,7 @@ namespace {
const_cast<char*>(_attribute.c_str()),
const_cast<char*>(ts.c_str()),
""};
const auto free_cond_input = irods::at_scope_exit{[&avuOp] { clearKeyVal(&avuOp.condInput); }};

if (_comm->clientUser.authInfo.authFlag >= LOCAL_PRIV_USER_AUTH) {
addKeyVal(&avuOp.condInput, ADMIN_KW, "");
Expand Down
19 changes: 18 additions & 1 deletion src/storage_tiering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -757,8 +757,25 @@ namespace irods {
};

execMyRuleInp_t exec_inp{};
rstrcpy(exec_inp.myRule, rule_obj.dump().c_str(), META_STR_LEN);
msParamArray_t* out_arr{};
// Capture out_arr pointer by reference because it is still nullptr at this point.
const auto free_inputs_and_outputs = irods::at_scope_exit{[&exec_inp, &out_arr] {
clearKeyVal(&exec_inp.condInput);

if (exec_inp.inpParamArray) {
// The second parameter with a value of 1 instructs the function to free the "inOutStruct".
clearMsParamArray(exec_inp.inpParamArray, 1);
std::free(exec_inp.inpParamArray);
}

if (out_arr) {
// The second parameter with a value of 1 instructs the function to free the "inOutStruct".
clearMsParamArray(out_arr, 1);
std::free(out_arr);
}
}};

rstrcpy(exec_inp.myRule, rule_obj.dump().c_str(), META_STR_LEN);
addKeyVal(
&exec_inp.condInput
, irods::KW_CFG_INSTANCE_NAME
Expand Down
Loading