This is an automated email from the ASF dual-hosted git repository.
pengzheng pushed a commit to branch feature/refactor_bundle_cache
in repository https://gitbox.apache.org/repos/asf/celix.git
The following commit(s) were added to refs/heads/feature/refactor_bundle_cache
by this push:
new 0decde3d Optimize celix_framework_utils_extractBundleEmbedded and test
it thoroughly.
0decde3d is described below
commit 0decde3dee01ae444feb4a6e5c9b21b19b221fd6
Author: PengZheng <[email protected]>
AuthorDate: Tue Apr 4 22:03:57 2023 +0800
Optimize celix_framework_utils_extractBundleEmbedded and test it thoroughly.
---
libs/error_injector/CMakeLists.txt | 1 +
libs/error_injector/asprintf/src/asprintf_ei.cc | 5 +-
libs/error_injector/dlfcn/CMakeLists.txt | 27 +++++++
.../asprintf_ei.cc => dlfcn/include/dlfcn_ei.h} | 27 ++++---
.../src/asprintf_ei.cc => dlfcn/src/dlfcn_ei.cc} | 27 +++----
libs/framework/gtest/CMakeLists.txt | 5 +-
.../CelixFrameworkUtilsErrorInjectionTestSuite.cc | 24 ++++++
libs/framework/src/celix_framework_utils.c | 90 ++++++++++++----------
8 files changed, 137 insertions(+), 69 deletions(-)
diff --git a/libs/error_injector/CMakeLists.txt
b/libs/error_injector/CMakeLists.txt
index 1d95086c..37f78c57 100644
--- a/libs/error_injector/CMakeLists.txt
+++ b/libs/error_injector/CMakeLists.txt
@@ -34,6 +34,7 @@ add_subdirectory(eventfd)
add_subdirectory(celix_bundle_ctx)
add_subdirectory(stat)
add_subdirectory(fts)
+add_subdirectory(dlfcn)
celix_subproject(ERROR_INJECTOR_MDNSRESPONDER "Option to enable building the
mdnsresponder error injector" OFF)
if (ERROR_INJECTOR_MDNSRESPONDER)
diff --git a/libs/error_injector/asprintf/src/asprintf_ei.cc
b/libs/error_injector/asprintf/src/asprintf_ei.cc
index 0c00c31c..3a235091 100644
--- a/libs/error_injector/asprintf/src/asprintf_ei.cc
+++ b/libs/error_injector/asprintf/src/asprintf_ei.cc
@@ -17,16 +17,19 @@
under the License.
*/
+#include "asprintf_ei.h"
#include <cstdarg>
#include <cstdio>
-#include "asprintf_ei.h"
+#include <errno.h>
extern "C" {
int __real_asprintf(char** buf, const char* format, ...);
CELIX_EI_DEFINE(asprintf, int)
int __wrap_asprintf(char** buf, const char* format, ...) {
+ errno = ENOMEM;
CELIX_EI_IMPL(asprintf);
+ errno = 0;
va_list args;
va_start(args, format);
int rc = vasprintf(buf, format, args);
diff --git a/libs/error_injector/dlfcn/CMakeLists.txt
b/libs/error_injector/dlfcn/CMakeLists.txt
new file mode 100644
index 00000000..9c8c2263
--- /dev/null
+++ b/libs/error_injector/dlfcn/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_library(dlfcn_ei STATIC src/dlfcn_ei.cc)
+
+target_include_directories(dlfcn_ei PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
+target_link_libraries(dlfcn_ei PUBLIC Celix::error_injector ${CMAKE_DL_LIBS})
+# It plays nicely with address sanitizer this way.
+target_link_options(dlfcn_ei INTERFACE
+ LINKER:--wrap,dlopen
+ LINKER:--wrap,dlerror
+)
+add_library(Celix::dlfcn_ei ALIAS dlfcn_ei)
diff --git a/libs/error_injector/asprintf/src/asprintf_ei.cc
b/libs/error_injector/dlfcn/include/dlfcn_ei.h
similarity index 68%
copy from libs/error_injector/asprintf/src/asprintf_ei.cc
copy to libs/error_injector/dlfcn/include/dlfcn_ei.h
index 0c00c31c..69c86678 100644
--- a/libs/error_injector/asprintf/src/asprintf_ei.cc
+++ b/libs/error_injector/dlfcn/include/dlfcn_ei.h
@@ -17,21 +17,20 @@
under the License.
*/
-#include <cstdarg>
-#include <cstdio>
-#include "asprintf_ei.h"
-
+#ifndef CELIX_DLFCN_EI_H
+#define CELIX_DLFCN_EI_H
+#ifdef __cplusplus
extern "C" {
+#endif
-int __real_asprintf(char** buf, const char* format, ...);
-CELIX_EI_DEFINE(asprintf, int)
-int __wrap_asprintf(char** buf, const char* format, ...) {
- CELIX_EI_IMPL(asprintf);
- va_list args;
- va_start(args, format);
- int rc = vasprintf(buf, format, args);
- va_end(args);
- return rc;
-}
+#include "celix_error_injector.h"
+#include <dlfcn.h>
+
+CELIX_EI_DECLARE(dlopen, void *);
+
+CELIX_EI_DECLARE(dlerror, char *);
+#ifdef __cplusplus
}
+#endif
+#endif //CELIX_DLFCN_EI_H
diff --git a/libs/error_injector/asprintf/src/asprintf_ei.cc
b/libs/error_injector/dlfcn/src/dlfcn_ei.cc
similarity index 66%
copy from libs/error_injector/asprintf/src/asprintf_ei.cc
copy to libs/error_injector/dlfcn/src/dlfcn_ei.cc
index 0c00c31c..90d7dd00 100644
--- a/libs/error_injector/asprintf/src/asprintf_ei.cc
+++ b/libs/error_injector/dlfcn/src/dlfcn_ei.cc
@@ -17,21 +17,22 @@
under the License.
*/
-#include <cstdarg>
-#include <cstdio>
-#include "asprintf_ei.h"
+#include "dlfcn_ei.h"
+#include <errno.h>
extern "C" {
-
-int __real_asprintf(char** buf, const char* format, ...);
-CELIX_EI_DEFINE(asprintf, int)
-int __wrap_asprintf(char** buf, const char* format, ...) {
- CELIX_EI_IMPL(asprintf);
- va_list args;
- va_start(args, format);
- int rc = vasprintf(buf, format, args);
- va_end(args);
- return rc;
+void *__real_dlopen(const char *__file, int __mode);
+CELIX_EI_DEFINE(dlopen, void *)
+void *__wrap_dlopen(const char *__file, int __mode) {
+ CELIX_EI_IMPL(dlopen);
+ return __real_dlopen(__file, __mode);
}
+char *__real_dlerror(void);
+CELIX_EI_DEFINE(dlerror, char *)
+char *__wrap_dlerror(void) {
+ CELIX_EI_IMPL(dlerror);
+ return __real_dlerror();
}
+
+}
\ No newline at end of file
diff --git a/libs/framework/gtest/CMakeLists.txt
b/libs/framework/gtest/CMakeLists.txt
index 2bbe5f27..95936fed 100644
--- a/libs/framework/gtest/CMakeLists.txt
+++ b/libs/framework/gtest/CMakeLists.txt
@@ -128,7 +128,10 @@ if (LINKER_WRAP_SUPPORTED)
celix_deprecated_utils_headers(test_framework_with_ei)
target_link_libraries(test_framework_with_ei PRIVATE
Celix::framework_obj
- Celix::malloc_ei Celix::utils_ei Celix::asprintf_ei
+ Celix::malloc_ei
+ Celix::utils_ei
+ Celix::asprintf_ei
+ Celix::dlfcn_ei
GTest::gtest GTest::gtest_main
)
diff --git
a/libs/framework/gtest/src/CelixFrameworkUtilsErrorInjectionTestSuite.cc
b/libs/framework/gtest/src/CelixFrameworkUtilsErrorInjectionTestSuite.cc
index 5a40cdbd..0be4f22d 100644
--- a/libs/framework/gtest/src/CelixFrameworkUtilsErrorInjectionTestSuite.cc
+++ b/libs/framework/gtest/src/CelixFrameworkUtilsErrorInjectionTestSuite.cc
@@ -27,7 +27,9 @@
#include "celix_framework_utils_private.h"
#include "celix_file_utils.h"
+#include "asprintf_ei.h"
#include "celix_utils_ei.h"
+#include "dlfcn_ei.h"
class CelixFrameworkUtilsErrorInjectionTestSuite : public ::testing::Test {
public:
@@ -40,6 +42,9 @@ public:
celix_ei_expect_celix_utils_extractZipFile(nullptr, 0, CELIX_SUCCESS);
celix_ei_expect_celix_utils_writeOrCreateString(nullptr, 0, nullptr);
celix_ei_expect_celix_utils_strdup(nullptr, 0, nullptr);
+ celix_ei_expect_dlopen(nullptr, 0, nullptr);
+ celix_ei_expect_dlerror(nullptr, 0, nullptr);
+ celix_ei_expect_asprintf(nullptr, 0, 0);
}
std::shared_ptr<celix::Framework> framework{};
};
@@ -52,6 +57,12 @@ TEST_F(CelixFrameworkUtilsErrorInjectionTestSuite,
testExtractEmbeddedBundle) {
auto status =
celix_framework_utils_extractBundle(framework->getCFramework(),
"embedded://simple_test_bundle1", testExtractDir);
EXPECT_EQ(status, CELIX_BUNDLE_EXCEPTION);
celix_utils_deleteDirectory(testExtractDir, nullptr);
+
+ celix_ei_expect_dlopen(CELIX_EI_UNKNOWN_CALLER, 0, nullptr, 2);
+ celix_ei_expect_dlerror(CELIX_EI_UNKNOWN_CALLER, 0, (char *)"Inject dl
error");
+ status = celix_framework_utils_extractBundle(framework->getCFramework(),
"embedded://simple_test_bundle1", testExtractDir);
+ EXPECT_EQ(status, CELIX_FRAMEWORK_EXCEPTION);
+ celix_utils_deleteDirectory(testExtractDir, nullptr);
}
TEST_F(CelixFrameworkUtilsErrorInjectionTestSuite, testExtractFileBundle) {
@@ -86,4 +97,17 @@ TEST_F(CelixFrameworkUtilsErrorInjectionTestSuite,
testIsBundleUrlValid) {
celix_ei_expect_celix_utils_strdup(CELIX_EI_UNKNOWN_CALLER, 0, nullptr);
auto valid =
celix_framework_utils_isBundleUrlValid(framework->getCFramework(),
"non-existing.zip", false);
EXPECT_FALSE(valid);
+
+ celix_ei_expect_dlopen(CELIX_EI_UNKNOWN_CALLER, 0, nullptr);
+ celix_ei_expect_dlerror(CELIX_EI_UNKNOWN_CALLER, 0, (char *)"Inject dl
error");
+ valid = celix_framework_utils_isBundleUrlValid(framework->getCFramework(),
"embedded://simple_test_bundle1", false);
+ EXPECT_FALSE(valid);
+
+ celix_ei_expect_asprintf(CELIX_EI_UNKNOWN_CALLER, 0, -1);
+ valid = celix_framework_utils_isBundleUrlValid(framework->getCFramework(),
"embedded://simple_test_bundle1", false);
+ EXPECT_FALSE(valid);
+
+ celix_ei_expect_asprintf(CELIX_EI_UNKNOWN_CALLER, 0, -1, 2);
+ valid = celix_framework_utils_isBundleUrlValid(framework->getCFramework(),
"embedded://simple_test_bundle1", false);
+ EXPECT_FALSE(valid);
}
diff --git a/libs/framework/src/celix_framework_utils.c
b/libs/framework/src/celix_framework_utils.c
index 4248aa73..8f288227 100644
--- a/libs/framework/src/celix_framework_utils.c
+++ b/libs/framework/src/celix_framework_utils.c
@@ -98,32 +98,57 @@ error_out:
return result;
}
-static bool celix_framework_utils_isEmbeddedBundleUrlValid(celix_framework_t
*fw, const char* bundleURL, bool silent) {
- bool valid = true;
-
+static celix_status_t
celix_framework_utils_locateEmbeddedBundle(celix_framework_t *fw, const char*
bundleURL, void **start, void **end, bool silent) {
+ const char *errStr = NULL;
+ celix_status_t status = CELIX_SUCCESS;
char* startSymbol = NULL;
char* endSymbol = NULL;
+ void* prog = NULL;
size_t offset = sizeof(EMBEDDED_URL_SCHEME)-1; //offset to remove the
EMBEDDED_URL_SCHEME part.
- asprintf(&startSymbol, "%s%s%s", EMBEDDED_BUNDLE_PREFIX, bundleURL+offset,
EMBEDDED_BUNDLE_START_POSTFIX);
- asprintf(&endSymbol, "%s%s%s", EMBEDDED_BUNDLE_PREFIX, bundleURL+offset,
EMBEDDED_BUNDLE_END_POSTFIX);
-
- void* prog = dlopen(NULL, RTLD_NOW);
- void* start = dlsym(prog, startSymbol);
- void* end = dlsym(prog, endSymbol);
- dlclose(prog);
-
- if (start == NULL || end == NULL) {
- valid = false;
+ if(asprintf(&startSymbol, "%s%s%s", EMBEDDED_BUNDLE_PREFIX,
bundleURL+offset, EMBEDDED_BUNDLE_START_POSTFIX) == -1) {
+ status = CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,errno);
+ errStr = strerror(errno);
+ goto start_asprintf_error;
+ }
+ if(asprintf(&endSymbol, "%s%s%s", EMBEDDED_BUNDLE_PREFIX,
bundleURL+offset, EMBEDDED_BUNDLE_END_POSTFIX) == -1) {
+ status = CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,errno);
+ errStr = strerror(errno);
+ goto end_asprintf_error;
}
- if (!valid && !silent) {
- FW_LOG(CELIX_LOG_LEVEL_ERROR, "Invalid bundle URL '%s'. Cannot find
start symbol %s and/or end symbol %s. Ensure that the bundle is embedded with
the CMake command `celix_target_embed_bundles` or
`celix_target_embed_bundle`.", bundleURL, startSymbol, endSymbol);
+ prog = dlopen(NULL, RTLD_NOW);
+ if (prog == NULL) {
+ status = CELIX_FRAMEWORK_EXCEPTION;
+ errStr = dlerror();
+ goto dlopen_error;
}
+ void *_start = dlsym(prog, startSymbol);
+ void *_end = dlsym(prog, endSymbol);
- free(startSymbol);
+ if (_start == NULL || _end == NULL) {
+ status = CELIX_ILLEGAL_ARGUMENT;
+ errStr = dlerror();
+ goto missing_symbol;
+ }
+ if (start != NULL) {
+ *start = _start;
+ }
+ if (end != NULL) {
+ *end = _end;
+ }
+missing_symbol:
+dlopen_error:
free(endSymbol);
-
- return valid;
+end_asprintf_error:
+ free(startSymbol);
+start_asprintf_error:
+ if (!silent) {
+ framework_logIfError(fw->logger, status, errStr, "Failed to locate
embedded bundle symbols for bundle '%s'.", bundleURL);
+ }
+ if (prog) {
+ dlclose(prog); // dlclose() will invalidate previous `errStr =
dlerror()`
+ }
+ return status;
}
static bool celix_framework_utils_isBundlePathNewerThan(celix_framework_t *fw,
const char* bundlePath, const struct timespec* time) {
@@ -179,27 +204,12 @@ static celix_status_t
celix_framework_utils_extractBundlePath(celix_framework_t
static celix_status_t
celix_framework_utils_extractBundleEmbedded(celix_framework_t *fw, const char*
embeddedBundle, const char* extractPath) {
FW_LOG(CELIX_LOG_LEVEL_TRACE, "Extracting embedded bundle `%s` to dir
`%s`", embeddedBundle, extractPath);
- char* startSymbol = NULL;
- char* endSymbol = NULL;
- asprintf(&startSymbol, "%s%s%s", EMBEDDED_BUNDLE_PREFIX, embeddedBundle,
EMBEDDED_BUNDLE_START_POSTFIX);
- asprintf(&endSymbol, "%s%s%s", EMBEDDED_BUNDLE_PREFIX, embeddedBundle,
EMBEDDED_BUNDLE_END_POSTFIX);
-
- void* prog = dlopen(NULL, RTLD_NOW);
- void* start = dlsym(prog, startSymbol);
- void* end = dlsym(prog, endSymbol);
- dlclose(prog);
-
- if (start == NULL || end == NULL) {
- FW_LOG(CELIX_LOG_LEVEL_ERROR, "Cannot extract embedded bundle, could
not find symbols `%s` and/or `%s` for embedded bundle `%s`", startSymbol,
endSymbol, embeddedBundle);
- free(startSymbol);
- free(endSymbol);
- return CELIX_ILLEGAL_ARGUMENT;
- }
- free(startSymbol);
- free(endSymbol);
-
+ void *start = NULL;
+ void *end = NULL;
const char* err = NULL;
- celix_status_t status = celix_utils_extractZipData(start, end-start,
extractPath, &err);
+
+ celix_status_t status = celix_framework_utils_locateEmbeddedBundle(fw,
embeddedBundle, &start, &end, true);
+ status = CELIX_DO_IF(status, celix_utils_extractZipData(start, end-start,
extractPath, &err));
if (status == CELIX_SUCCESS) {
FW_LOG(CELIX_LOG_LEVEL_TRACE, "Embedded bundle zip `%s` extracted to
`%s`", embeddedBundle, extractPath);
}
@@ -219,7 +229,7 @@ celix_status_t
celix_framework_utils_extractBundle(celix_framework_t *fw, const
if (strncasecmp(FILE_URL_SCHEME, trimmedUrl, fileSchemeLen) == 0) {
status = celix_framework_utils_extractBundlePath(fw, trimmedUrl +
fileSchemeLen, extractPath);
} else if (strncasecmp(EMBEDDED_URL_SCHEME, trimmedUrl, embeddedSchemeLen)
== 0) {
- status = celix_framework_utils_extractBundleEmbedded(fw, trimmedUrl +
embeddedSchemeLen, extractPath);
+ status = celix_framework_utils_extractBundleEmbedded(fw, trimmedUrl,
extractPath);
} else {
status = celix_framework_utils_extractBundlePath(fw, trimmedUrl,
extractPath);
}
@@ -246,7 +256,7 @@ bool
celix_framework_utils_isBundleUrlValid(celix_framework_t *fw, const char *b
valid = loc != NULL;
celix_utils_freeStringIfNotEqual(buffer, loc);
} else if (strncasecmp(EMBEDDED_URL_SCHEME, trimmedUrl, embeddedSchemeLen)
== 0) {
- valid = celix_framework_utils_isEmbeddedBundleUrlValid(fw, trimmedUrl,
silent);
+ valid = (celix_framework_utils_locateEmbeddedBundle(fw, trimmedUrl,
NULL, NULL, silent) == CELIX_SUCCESS);
} else if (strcasestr(trimmedUrl, "://")) {
valid = false;
if (!silent) {