From cacee63bb55f791a3da5b4d97f42911a6cb47b45 Mon Sep 17 00:00:00 2001 From: Demitri Swan Date: Tue, 18 Feb 2020 10:56:35 -0800 Subject: [PATCH] #14 - Fixing pthreads_rwlock_unlock issue for older OS (#15) * Support Build Matrix * Force C11 on compile * pthreawd_rwlock_unlock "The pthread_rwlock_unlock() function is called to release a lock held on the read-write lock object referenced by rwlock. Results are undefined if the read-write lock rwlock is not held by the calling thread." On older flavors of linux this can be problematic. This PR removes these calls from destructor functions. * Using MHD_USE_SELECT_INTERNALLY for MHD_flag in smoke test * Update example to use updated MHD_flag --- .gitignore | 1 + .travis.yml | 10 ++++- Makefile | 8 +--- README.md | 6 +++ auto | 3 +- autolib/autolib.sh | 3 +- autolib/cmd/dev | 28 ++++++++----- autolib/docker.sh | 53 +++++++++++++++++++++++++ docker/Dockerfile | 20 ---------- example/main.c | 2 +- prom/CMakeLists.txt | 2 + prom/src/prom_map.c | 6 --- prom/src/prom_metric.c | 6 --- prom/src/prom_metric_sample_histogram.c | 3 -- promhttp/CMakeLists.txt | 2 + promtest/CMakeLists.txt | 2 + promtest/test/promtest_counter.c | 2 +- promtest/test/promtest_gauge.c | 2 +- 18 files changed, 101 insertions(+), 58 deletions(-) create mode 100644 autolib/docker.sh delete mode 100644 docker/Dockerfile diff --git a/.gitignore b/.gitignore index 87bb3e3..f729b04 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +docker/Dockerfile .vscode prom/build/* promhttp/build/* diff --git a/.travis.yml b/.travis.yml index 4b111d2..f95a088 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,4 +5,12 @@ language: c services: - docker -script: make \ No newline at end of file +script: make + +jobs: + include: + - env: DOCKER_IMAGE=ubuntu:18.04 + - env: DOCKER_IMAGE=ubuntu:16.04 + - env: DOCKER_IMAGE=debian:buster + - env: DOCKER_IMAGE=debian:stretch + - env: DOCKER_IMAGE=debian:jessie diff --git a/Makefile b/Makefile index fb2042a..39a5117 100644 --- a/Makefile +++ b/Makefile @@ -13,17 +13,13 @@ default: changed_files @echo -e "\033[1;32mNothing to build\033[0m" endif -build_and_test: changed_files docker clean build test package smoke +build_and_test: changed_files clean build test package smoke .PHONY: build_and_test all: build_and_test docs .PHONY: all -docker: - pushd docker && make -.PHONY: docker - -clean: docker +clean: ./auto dev -e auto -a clean build: clean diff --git a/README.md b/README.md index 4e00181..099d68b 100644 --- a/README.md +++ b/README.md @@ -73,3 +73,9 @@ communication process so please do not be shy. Speak up! ## Misc * Language level: C11 +* Operating Systems: + * Ubuntu 18.04 + * Ubuntu 16.04 + * Debian Buster + * Debian Stretch + * Debian Jessie diff --git a/auto b/auto index 4aaa6ba..120d4e2 100755 --- a/auto +++ b/auto @@ -10,7 +10,8 @@ if [[ "$AUTO_DEBUG" == "1" ]]; then export AUTO_DEBUG=1 fi -PROJECT_ROOT=$(pushd $(dirname $0) > /dev/null; echo $PWD; popd > /dev/null) +export PROJECT_ROOT=$(pushd $(dirname $0) > /dev/null; echo $PWD; popd > /dev/null) +export DOCKER_IMAGE PROGRAM_NAME="$(basename $0)" usage(){ diff --git a/autolib/autolib.sh b/autolib/autolib.sh index 54ff558..4230995 100644 --- a/autolib/autolib.sh +++ b/autolib/autolib.sh @@ -4,5 +4,6 @@ lib="$(dirname ${BASH_SOURCE[0]})" source "${lib}/output.sh" source "${lib}/build.sh" +source "${lib}/docker.sh" source "${lib}/env.sh" -source "${lib}/test.sh" \ No newline at end of file +source "${lib}/test.sh" diff --git a/autolib/cmd/dev b/autolib/cmd/dev index 012798f..2f5ed13 100755 --- a/autolib/cmd/dev +++ b/autolib/cmd/dev @@ -21,6 +21,9 @@ MUST NOT execute this command from an existing docker container. -e Execute the following executable -a Pass an argument to the executable given by -e. You may specify this flag multiple times. The order is preserved. +-i The docker image to use. + Default: ubuntu:18.04 + Options: ubuntu:18.04, ubuntu:16.04, debian:buster, debian:stretch, debian:jessie EOF usage() { @@ -43,21 +46,21 @@ EOF source $(dirname ${BASH_SOURCE[0]})/../autolib.sh +declare DOCKER_IMAGE=${DOCKER_IMAGE:=ubuntu:18.04} declare DOCKER_EXEC declare -a DOCKER_EXEC_ARGS run(){ local r - if ! { docker image list | grep -q prometheus-client-c-dev; }; then - autolib_output_banner "Building development container" - pushd docker > /dev/null || return $? - make || { - r=$? - outlib_output_error "Docker Build Failure" - return $r - } - popd > /dev/null - fi + autolib_output_banner "Building development container" + autolib_write_dockerfile "$DOCKER_IMAGE" || return $? + pushd docker > /dev/null || return $? + make || { + r=$? + outlib_output_error "Docker Build Failure" + return $r + } + popd > /dev/null autolib_output_banner "Entering development environment" declare -a args @@ -75,11 +78,14 @@ run(){ } main(){ - while getopts "he:a:" opt; do + while getopts "he:a:i:" opt; do case $opt in ( h ) { usage && exit 0 } ;; + ( i ) { + DOCKER_IMAGE="$OPTARG" + } ;; ( e ) { DOCKER_EXEC="$OPTARG" } ;; diff --git a/autolib/docker.sh b/autolib/docker.sh new file mode 100644 index 0000000..bfef40d --- /dev/null +++ b/autolib/docker.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +lib="$(dirname ${BASH_SOURCE[0]})" +source "${lib}/output.sh" + +PROJECT_ROOT=$(pushd "$(dirname ${BASH_SOURCE[0]})/.." > /dev/null; echo $PWD; popd > /dev/null) + +autolib_debian_template(){ + cat <<'EOF' +FROM __DOCKER_IMAGE__ + +RUN apt-get update && \ + apt-get install -y apt-utils && \ + apt-get install -y curl tar build-essential git pkg-config gdb valgrind gcc libmicrohttpd-dev doxygen graphviz && \ + curl -sL https://github.com/Kitware/CMake/releases/download/v3.14.5/cmake-3.14.5-Linux-x86_64.tar.gz | tar xzf - -C /opt && \ + cp /opt/cmake-3.14.5-Linux-x86_64/bin/* /usr/local/bin/ && \ + cp -R /opt/cmake-3.14.5-Linux-x86_64/share/cmake-3.14 /usr/local/share/ && \ + curl -sL https://dl.google.com/go/go1.13.1.linux-amd64.tar.gz 2> /dev/null | tar xzf - -C /usr/local && \ + mkdir -p /gopath/{src,bin} && \ + printf 'export GOPATH=/gopath\nexport PATH=$PATH:/usr/local/go/bin:/gopath/bin\n' > /root/.bash_profile && \ + printf '#!/usr/bin/env bash\nsource /root/.bash_profile\nexec /bin/bash $@\n' > /entrypoint && \ + chmod +x /entrypoint && \ + GOPATH=/gopath /usr/local/go/bin/go get github.com/prometheus/prom2json && \ + GOPATH=/gopath /usr/local/go/bin/go install github.com/prometheus/prom2json/cmd/prom2json && \ + GOPATH=/gopath /usr/local/go/bin/go get github.com/git-chglog/git-chglog && \ + GOPATH=/gopath /usr/local/go/bin/go install github.com/git-chglog/git-chglog/cmd/git-chglog && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /code +ENTRYPOINT ["/entrypoint"] + +EOF +} + +autolib_write_dockerfile(){ + local docker_image="$1" + local r + case "$docker_image" in + ( ubuntu:18.04 | ubuntu:16.04 | debian:buster | debian:stretch | debian:jessie ) { + autolib_debian_template | sed "s/__DOCKER_IMAGE__/$docker_image/g" > ${PROJECT_ROOT}/docker/Dockerfile || { + r=$? + autolib_output_error "failed to generate dockerfile" + return $r + } + } ;; + + ( * ) { + r=1 + autolib_output_error "unsupported DOCKER_IMAGE: $docker_image" + return $r + } ;; + esac +} \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index 48b0e52..0000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM ubuntu:18.04 - -RUN apt-get update && \ - apt-get install -y apt-utils && \ - apt-get install -y curl tar build-essential git pkg-config gdb valgrind gcc libmicrohttpd-dev doxygen graphviz && \ - curl -L https://dl.google.com/go/go1.13.1.linux-amd64.tar.gz 2> /dev/null | tar xzvf - -C /usr/local && \ - mkdir -p /gopath/{src,bin} && \ - printf 'export GOPATH=/gopath\nexport PATH=$PATH:/usr/local/go/bin:/gopath/bin\n' > /root/.bash_profile && \ - printf '#!/usr/bin/env bash\nsource /root/.bash_profile\nexec /bin/bash $@\n' > /entrypoint && \ - chmod +x /entrypoint && \ - GOPATH=/gopath /usr/local/go/bin/go get github.com/prometheus/prom2json && \ - GOPATH=/gopath /usr/local/go/bin/go install github.com/prometheus/prom2json/cmd/prom2json && \ - GOPATH=/gopath /usr/local/go/bin/go get github.com/git-chglog/git-chglog && \ - GOPATH=/gopath /usr/local/go/bin/go install github.com/git-chglog/git-chglog/cmd/git-chglog && \ - curl -L https://github.com/Kitware/CMake/releases/download/v3.15.0-rc1/cmake-3.15.0-rc1.tar.gz | tar xzvf - -C /tmp/ && \ - cd /tmp/cmake-3.15.0-rc1 && ./bootstrap && make && make install && \ - rm -rf /var/lib/apt/lists/* - -WORKDIR /code -ENTRYPOINT ["/entrypoint"] \ No newline at end of file diff --git a/example/main.c b/example/main.c index c93e149..d695d12 100644 --- a/example/main.c +++ b/example/main.c @@ -74,7 +74,7 @@ int main(int argc, const char **argv) { } - struct MHD_Daemon *daemon = promhttp_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD, 8000, NULL, NULL); + struct MHD_Daemon *daemon = promhttp_start_daemon(MHD_USE_SELECT_INTERNALLY, 8000, NULL, NULL); if (daemon == NULL) { return 1; } diff --git a/prom/CMakeLists.txt b/prom/CMakeLists.txt index dc0c494..aaa8877 100644 --- a/prom/CMakeLists.txt +++ b/prom/CMakeLists.txt @@ -1,4 +1,6 @@ cmake_minimum_required(VERSION 3.14.5) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) execute_process( COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION diff --git a/prom/src/prom_map.c b/prom/src/prom_map.c index a36cad7..677c66d 100644 --- a/prom/src/prom_map.c +++ b/prom/src/prom_map.c @@ -136,12 +136,6 @@ int prom_map_destroy(prom_map_t *self) { prom_free(self->addrs); self->addrs = NULL; - r = pthread_rwlock_unlock(self->rwlock); - if (r) { - PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR); - ret = r; - } - r = pthread_rwlock_destroy(self->rwlock); if (r) { PROM_LOG(PROM_PTHREAD_RWLOCK_DESTROY_ERROR) diff --git a/prom/src/prom_metric.c b/prom/src/prom_metric.c index cbfab34..47d7fdf 100644 --- a/prom/src/prom_metric.c +++ b/prom/src/prom_metric.c @@ -119,12 +119,6 @@ int prom_metric_destroy(prom_metric_t *self) { self->formatter = NULL; if (r) ret = r; - r = pthread_rwlock_unlock(self->rwlock); - if (r) { - PROM_LOG(PROM_PTHREAD_RWLOCK_UNLOCK_ERROR); - ret = r; - } - r = pthread_rwlock_destroy(self->rwlock); if (r) { PROM_LOG(PROM_PTHREAD_RWLOCK_DESTROY_ERROR); diff --git a/prom/src/prom_metric_sample_histogram.c b/prom/src/prom_metric_sample_histogram.c index 4fe6cac..28533b7 100644 --- a/prom/src/prom_metric_sample_histogram.c +++ b/prom/src/prom_metric_sample_histogram.c @@ -327,9 +327,6 @@ int prom_metric_sample_histogram_destroy(prom_metric_sample_histogram_t *self) { if (r) ret = r; self->metric_formatter = NULL; - r = pthread_rwlock_unlock(self->rwlock); - if (r) ret = r; - r = pthread_rwlock_destroy(self->rwlock); if (r) ret = r; diff --git a/promhttp/CMakeLists.txt b/promhttp/CMakeLists.txt index e0451d0..9565c8d 100644 --- a/promhttp/CMakeLists.txt +++ b/promhttp/CMakeLists.txt @@ -1,4 +1,6 @@ cmake_minimum_required(VERSION 3.14.5) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) execute_process( COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION diff --git a/promtest/CMakeLists.txt b/promtest/CMakeLists.txt index 32ae3b0..3c6de45 100644 --- a/promtest/CMakeLists.txt +++ b/promtest/CMakeLists.txt @@ -1,4 +1,6 @@ cmake_minimum_required(VERSION 3.14.5) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) execute_process( COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/../VERSION diff --git a/promtest/test/promtest_counter.c b/promtest/test/promtest_counter.c index a2940f7..c57cd56 100644 --- a/promtest/test/promtest_counter.c +++ b/promtest/test/promtest_counter.c @@ -105,7 +105,7 @@ int promtest_counter_setup(void) { promhttp_set_active_collector_registry(NULL); // Start the HTTP server - promtest_daemon = promhttp_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD, 8000, NULL, NULL); + promtest_daemon = promhttp_start_daemon(MHD_USE_SELECT_INTERNALLY, 8000, NULL, NULL); if (promtest_daemon == NULL) return 1; else return 0; diff --git a/promtest/test/promtest_gauge.c b/promtest/test/promtest_gauge.c index a8202d2..c33450d 100644 --- a/promtest/test/promtest_gauge.c +++ b/promtest/test/promtest_gauge.c @@ -105,7 +105,7 @@ int promtest_gauge_setup(void) { promhttp_set_active_collector_registry(NULL); // Start the HTTP server - promtest_daemon = promhttp_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD, 8000, NULL, NULL); + promtest_daemon = promhttp_start_daemon(MHD_USE_SELECT_INTERNALLY, 8000, NULL, NULL); if (promtest_daemon == NULL) return 1; else return 0;