Skip to content

Commit

Permalink
Try run on apple silicon. (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheredom committed Feb 5, 2024
1 parent 9c733b6 commit b994b21
Show file tree
Hide file tree
Showing 9 changed files with 1,035 additions and 303 deletions.
22 changes: 17 additions & 5 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,20 @@ jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
os: [ubuntu-latest, windows-latest, macos-11, macos-14]
type: [Debug, RelWithDebInfo, MinSizeRel, Release]
compiler: [default, clang, gcc]
compiler: [default, clang, gcc, tcc]
exclude:
- {os: "macOS-latest", compiler: "clang"}
- {os: "macOS-latest", compiler: "gcc"}
- {os: "macos-11", compiler: "clang"}
- {os: "macos-11", compiler: "gcc"}
- {os: "macos-11", compiler: "tcc"}
- {os: "macos-14", compiler: "clang"}
- {os: "macos-14", compiler: "gcc"}
- {os: "macos-14", compiler: "tcc"}
- {os: "ubuntu-latest", compiler: "default"}
- {os: "ubuntu-latest", compiler: "default"}
- {os: "windows-latest", compiler: "gcc"}
- {os: "windows-latest", compiler: "tcc"}
runs-on: ${{ matrix.os }}

steps:
Expand All @@ -28,7 +34,7 @@ jobs:

- name: Setup dependencies (Ubuntu)
if: startsWith(matrix.os, 'ubuntu')
run: sudo apt-get install -y gcc-10 g++-10 clang
run: sudo apt-get install -y gcc-10 g++-10 clang tcc

- name: Setup dependencies (MinGW)
if: matrix.compiler == 'gcc' && startsWith(matrix.os, 'windows')
Expand All @@ -46,6 +52,12 @@ jobs:
working-directory: ${{github.workspace}}/build
run: cmake $GITHUB_WORKSPACE/test -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DCMAKE_C_COMPILER=gcc-10 -DCMAKE_CXX_COMPILER=g++-10

- name: Configure CMake with TCC (Ubuntu)
shell: bash
if: matrix.compiler == 'tcc' && startsWith(matrix.os, 'ubuntu')
working-directory: ${{github.workspace}}/build
run: cmake $GITHUB_WORKSPACE/test -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DCMAKE_C_COMPILER=tcc -DCMAKE_CXX_COMPILER=g++-10

- name: Configure CMake with MinGW
shell: bash
if: matrix.compiler == 'gcc' && startsWith(matrix.os, 'windows')
Expand Down
56 changes: 56 additions & 0 deletions .github/workflows/sanitizers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Sanitizers

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macOS-latest]
type: [Debug, RelWithDebInfo, MinSizeRel, Release]
sanitizer: [address, memory, undefined]
exclude:
- {os: "macOS-latest", sanitizer: "memory"}
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4

- name: Create Build Environment
run: cmake -E make_directory ${{github.workspace}}/build

- name: Setup dependencies
if: startsWith(matrix.os, 'ubuntu')
run: sudo apt-get install -y clang

- name: Configure CMake (macOS)
shell: bash
if: startsWith(matrix.os, 'macOS')
working-directory: ${{github.workspace}}/build
run: cmake $GITHUB_WORKSPACE/test -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DSUBPROCESS_USE_SANITIZER=${{ matrix.sanitizer }}

- name: Configure CMake with Clang (Ubuntu)
shell: bash
if: startsWith(matrix.os, 'ubuntu')
working-directory: ${{github.workspace}}/build
run: cmake $GITHUB_WORKSPACE/test -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DSUBPROCESS_USE_SANITIZER=${{ matrix.sanitizer }}

- name: Build
working-directory: ${{github.workspace}}/build
shell: bash
run: cmake --build . --config ${{ matrix.type }}

- name: Test
working-directory: ${{github.workspace}}/build
shell: bash
run: if [ "${{ matrix.os }}" == "windows-latest" ] && [ "${{ matrix.compiler }}" != "gcc" ]; then cd ${{ matrix.type }}; fi; ./subprocess_test

- name: Test with Multithreading
working-directory: ${{github.workspace}}/build
shell: bash
if: startsWith(matrix.os, 'windows')
run: if [ "${{ matrix.os }}" == "windows-latest" ] && [ "${{ matrix.compiler }}" != "gcc" ]; then cd ${{ matrix.type }}; fi; ./subprocess_mt_test
31 changes: 25 additions & 6 deletions subprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,23 @@
#pragma warning(pop)
#endif

#if defined(__TINYC__)
#define SUBPROCESS_ATTRIBUTE(a) __attribute((a))
#else
#define SUBPROCESS_ATTRIBUTE(a) __attribute__((a))
#endif

#if defined(_MSC_VER)
#define subprocess_pure
#define subprocess_weak __inline
#define subprocess_tls __declspec(thread)
#elif defined(__MINGW32__)
#define subprocess_pure __attribute__((pure))
#define subprocess_weak static __attribute__((used))
#define subprocess_pure SUBPROCESS_ATTRIBUTE(pure)
#define subprocess_weak static SUBPROCESS_ATTRIBUTE(used)
#define subprocess_tls __thread
#elif defined(__clang__) || defined(__GNUC__)
#define subprocess_pure __attribute__((pure))
#define subprocess_weak __attribute__((weak))
#elif defined(__clang__) || defined(__GNUC__) || defined(__TINYC__)
#define subprocess_pure SUBPROCESS_ATTRIBUTE(pure)
#define subprocess_weak SUBPROCESS_ATTRIBUTE(weak)
#define subprocess_tls __thread
#else
#error Non clang, non gcc, non MSVC compiler found!
Expand Down Expand Up @@ -415,6 +421,13 @@ struct subprocess_s {
#pragma clang diagnostic pop
#endif

#if defined(__clang__)
#if __has_warning("-Wunsafe-buffer-usage")
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
#endif
#endif

#if defined(_WIN32)
subprocess_weak int subprocess_create_named_pipe_helper(void **rd, void **wr);
int subprocess_create_named_pipe_helper(void **rd, void **wr) {
Expand Down Expand Up @@ -889,7 +902,7 @@ int subprocess_create_ex(const char *const commandLine[], int options,
out_process->stdout_file = fdopen(stdoutfd[0], "rb");

// Should we use async behaviour ?
if(options & subprocess_option_enable_async){
if (options & subprocess_option_enable_async) {
fd = fileno(out_process->stdout_file);
fd_flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK);
Expand Down Expand Up @@ -1182,6 +1195,12 @@ int subprocess_alive(struct subprocess_s *const process) {
return is_alive;
}

#if defined(__clang__)
#if __has_warning("-Wunsafe-buffer-usage")
#pragma clang diagnostic pop
#endif
#endif

#if defined(__cplusplus)
} // extern "C"
#endif
Expand Down
16 changes: 14 additions & 2 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
#
# For more information, please refer to <http://unlicense.org/>

project(process)
project(subprocess)
cmake_minimum_required(VERSION 3.15)

set(SUBPROCESS_USE_SANITIZER "" CACHE STRING "Set which Clang Sanitizer to use")

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../)

add_executable(process_return_zero process_return_zero.c)
Expand All @@ -47,7 +49,7 @@ add_executable(process_fail_stackoverflow process_fail_stackoverflow.c)
add_executable(process_hung process_hung.c)
add_executable(process_stdout_data process_stdout_data.c)
add_executable(process_stdout_poll process_stdout_poll.c)
add_executable(process_stdout_poll_nodata process_stdout_poll_nodata.c)
add_executable(process_stdout_poll_wait_first process_stdout_poll_wait_first.c)
add_executable(process_stderr_poll process_stderr_poll.c)
add_executable(process_stdout_large process_stdout_large.c)
add_executable(process_call_return_argc process_call_return_argc.c)
Expand All @@ -62,6 +64,11 @@ add_executable(subprocess_test
post_windows.cpp
)

if(NOT "${SUBPROCESS_USE_SANITIZER}" STREQUAL "")
target_compile_options(subprocess_test PUBLIC -fno-omit-frame-pointer -fsanitize=${SUBPROCESS_USE_SANITIZER})
target_link_options(subprocess_test PUBLIC -fno-omit-frame-pointer -fsanitize=${SUBPROCESS_USE_SANITIZER})
endif()

set(MSVC_FLAGS "/Wall /WX /wd4514 /wd4710 /wd4711 /wd5045")

if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
Expand Down Expand Up @@ -118,6 +125,11 @@ add_executable(subprocess_mt_test
post_windows.cpp
)

if(NOT "${SUBPROCESS_USE_SANITIZER}" STREQUAL "")
target_compile_options(subprocess_mt_test PUBLIC -fno-omit-frame-pointer -fsanitize=${SUBPROCESS_USE_SANITIZER})
target_link_options(subprocess_mt_test PUBLIC -fno-omit-frame-pointer -fsanitize=${SUBPROCESS_USE_SANITIZER})
endif()

if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
target_compile_options(subprocess_mt_test PUBLIC "/MT")
Expand Down
64 changes: 45 additions & 19 deletions test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ __declspec(dllimport) int __stdcall SetEnvironmentVariableA(const char *,

#include "subprocess.h"

#if defined(__clang__)
#if __has_warning("-Wunsafe-buffer-usage")
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
#endif
#endif

UTEST(create, subprocess_destroy_is_idempotent) {
const char *const commandLine[] = {"./process_return_zero", 0};
struct subprocess_s process;
Expand Down Expand Up @@ -284,8 +291,8 @@ UTEST(create, subprocess_return_special_argv) {
}

UTEST(create, subprocess_return_lpcmdline) {
const char *const commandLine[] = {"./process_return_lpcmdline",
"noquotes", "should be quoted", 0};
const char *const commandLine[] = {"./process_return_lpcmdline", "noquotes",
"should be quoted", 0};
struct subprocess_s process;
int ret = -1;
size_t cmp_index, index;
Expand All @@ -306,7 +313,8 @@ UTEST(create, subprocess_return_lpcmdline) {

// comparing from the back skips exe name
cmp_index = strlen(compare) - 1;
for (index = strlen(temp) - 1; index != 0 && cmp_index != 0; index--,cmp_index--) {
for (index = strlen(temp) - 1; index != 0 && cmp_index != 0;
index--, cmp_index--) {
if (temp[index] != compare[cmp_index])
ASSERT_TRUE(0);
}
Expand Down Expand Up @@ -594,7 +602,7 @@ UTEST(subprocess, read_stdout_async_small) {
ASSERT_EQ(0, subprocess_create(commandLine, subprocess_option_enable_async,
&process));

while(subprocess_alive(&process)) {
while (subprocess_alive(&process)) {
bytes_read = subprocess_read_stdout(&process, data + index,
sizeof(data) - 1 - index);
index += bytes_read;
Expand Down Expand Up @@ -624,7 +632,7 @@ UTEST(subprocess, read_stdout_async) {
ASSERT_EQ(0, subprocess_create(commandLine, subprocess_option_enable_async,
&process));

while(subprocess_alive(&process)) {
while (subprocess_alive(&process)) {
bytes_read = subprocess_read_stdout(&process, data + index,
sizeof(data) - 1 - index);
index += bytes_read;
Expand All @@ -643,40 +651,48 @@ UTEST(subprocess, read_stdout_async) {
ASSERT_EQ(ret, 0);
}

UTEST(subprocess, read_stdout_async_nodata) {
const char *const commandLine[] = {"./process_stdout_poll_nodata", 0};
UTEST(subprocess, poll_stdout_async) {
const char *const commandLine[] = {"./process_stdout_poll", "16384", 0};
struct subprocess_s process;
int ret = -1;
static char data[14 + 1] = {0};
static char data[1048576 + 1] = {0};
unsigned index = 0;
unsigned bytes_read = 0;

ASSERT_EQ(0, subprocess_create(commandLine, subprocess_option_enable_async,
&process));

while(subprocess_alive(&process)) {
while (subprocess_alive(&process)) {
bytes_read = subprocess_read_stdout(&process, data + index,
sizeof(data) - 1 - index);
index += bytes_read;

// Send any character to the subprocess to tell it to pursuit
if (bytes_read == 0) {
// Send the control character to the subprocess to tell it to stop after
// we've read at least one thing from it's stdout (meaning the read was
// definitely async).
if (bytes_read > 0) {
fputc('s', subprocess_stdin(&process));
fflush(subprocess_stdin(&process));
}

index += bytes_read;
}

ASSERT_EQ(15u, bytes_read);
ASSERT_EQ(15u, index);
ASSERT_TRUE(0 == memcmp("Hello, world!", data, 14));
ASSERT_EQ(212992u, index);

for (index = 0; index < 16384; index++) {
const char *const helloWorld = "Hello, world!";
ASSERT_TRUE(0 == memcmp(data + (index * strlen(helloWorld)), helloWorld,
strlen(helloWorld)));
}

ASSERT_EQ(0, subprocess_join(&process, &ret));
ASSERT_EQ(0, subprocess_destroy(&process));
ASSERT_EQ(ret, 0);
}

UTEST(subprocess, poll_stdout_async) {
const char *const commandLine[] = {"./process_stdout_poll", "16384", 0};
UTEST(subprocess, poll_stdout_async_wait_first) {
const char *const commandLine[] = {"./process_stdout_poll_wait_first",
"16384", 0};
struct subprocess_s process;
int ret = -1;
static char data[1048576 + 1] = {0};
Expand All @@ -686,14 +702,24 @@ UTEST(subprocess, poll_stdout_async) {
ASSERT_EQ(0, subprocess_create(commandLine, subprocess_option_enable_async,
&process));

while(subprocess_alive(&process)) {
bytes_read =
subprocess_read_stdout(&process, data + index, sizeof(data) - 1 - index);

// We first have zero bytes read because we haven't wrote the control
// character to stdin.
ASSERT_EQ(0u, bytes_read);

fputc('s', subprocess_stdin(&process));
fflush(subprocess_stdin(&process));

while (subprocess_alive(&process)) {
bytes_read = subprocess_read_stdout(&process, data + index,
sizeof(data) - 1 - index);

// Send the control character to the subprocess to tell it to stop after
// we've read at least one thing from it's stdout (meaning the read was
// definitely async).
if (index == 0) {
if (bytes_read > 0) {
fputc('s', subprocess_stdin(&process));
fflush(subprocess_stdin(&process));
}
Expand Down
8 changes: 6 additions & 2 deletions test/process_call_return_argc.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@
// For more information, please refer to <http://unlicense.org/>

#include <subprocess.h>
#ifdef __MINGW32__
#include <unistd.h> // chdir

#if defined(_MSC_VER)
#include <direct.h>
#define chdir(x) _chdir(x)
#elif defined(__MINGW32__)
#include <unistd.h> // chdir
#endif

int main(int argc, const char *const argv[]) {
Expand Down
2 changes: 1 addition & 1 deletion test/process_return_lpcmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ int main(int argc, const char *const argv[]) {
printf("\"%s\"", argv[i]);
else
printf("%s", argv[i]);
if (i != (argc-1))
if (i != (argc - 1))
printf(" ");
}
#endif
Expand Down
Loading

0 comments on commit b994b21

Please sign in to comment.