zelang-dev / c-coroutine

A simple C coroutine library, with multithreading and more, the Go and C++20 style way.
https://zelang-dev.github.io/c-coroutine/
MIT License
81 stars 2 forks source link

Compile errors on macOS (clang) #1

Closed onderweg closed 1 year ago

onderweg commented 1 year ago

Hi,

Thanks for creating this library!

When building on macOS, I get two compile errors:

c-coroutine/src/coroutine.c:147:9: error: non-void function 'co_await' should return a value [-Wreturn-type]
        return;
        ^
c-coroutine/src/coroutine.c:237:9: error: non-void function 'co_group_get_result' should return a value [-Wreturn-type]
        return;

Probably easy solvable when familiar with the inner workings of the library, but I don't know what a proper return value should be for these functions.

binarycraft007 commented 1 year ago

same error when I tried to port it to the zig build system:

zig build-lib coroutine Debug native: error: error(compilation): clang failed with stderr: /home/elliot/projects/c-coroutine/src/coroutine.c:147:9: error: non-void function 'co_await' should return a value [-Wreturn-type]
/home/elliot/projects/c-coroutine/src/coroutine.c:189:54: warning: argument to 'sizeof' in 'memcmp' call is the same pointer type 'wait_group_t *' (aka 'struct oa_hash_s *') as the destination; expected 'hash_t' (aka 'struct oa_hash_s') or an explicit length [-Wsizeof-pointer-memaccess]
/home/elliot/projects/c-coroutine/src/coroutine.c:237:9: error: non-void function 'co_group_get_result' should return a value [-Wreturn-type]
TheTechsTech commented 1 year ago

I'm not using any special compile flags, just defaults, so under Ubuntu gcc it's just an warning, compiling proceeds. I guess clang different default behavior.

Scanning dependencies of target coroutine
[ 46%] Building C object CMakeFiles/coroutine.dir/src/coroutine.c.o
/mnt/c/Users/Lenovo/Documents/c-coroutine/src/coroutine.c: In function ‘co_await’:
/mnt/c/Users/Lenovo/Documents/c-coroutine/src/coroutine.c:147:9: warning: ‘return’ with no value, in function returning non-void   
  147 |         return;
      |         ^~~~~~
/mnt/c/Users/Lenovo/Documents/c-coroutine/src/coroutine.c:142:9: note: declared here
  142 | value_t co_await(callable_t fn, void_t arg) {
      |         ^~~~~~~~
[ 48%] Linking C static library ../coroutine-built/libcoroutine.a

Currently I'm working on how to handle errors returned by libuv calls. "No return" is just temporary fix. Took me some time to figure it out, the line was return ((values_t *)0)->value; to indicate a NULL union value, that caused segfaults. The real fix for the warning and now error is being worked.

So you could just comment lines out to compile immediately, or look up clang compile flags to pass to cmake. Commenting out will only indicate bug in example co_uv_listen.c, if there is an connect problem like "address already in use" which is what I recently solved.

Once I got a working routine I had to reboot computer. I got that initial message after many segfaults on same port, can't find way to make error happen again.

@binarycraft007, @onderweg , If you know a way to force "address already in use" on a port or address, for further testing let me know.

binarycraft007 commented 1 year ago

@TheTechsTech my log above showed that it's -Wreturn-type, so pass -Wno-return-type solved the compile error, but it's just a workaround anyway, btw, why pthread4w, I think there is winpthreads for mingw64 which provides other unix libc functions, and it's a better maintained project, github mirror: https://github.com/mingw-w64/mingw-w64/tree/master/mingw-w64-libraries/winpthreads.

I am not using cmake, but zig build system, btw, is there any modification to libuv, I am using system's libuv for now

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const lib = b.addStaticLibrary(.{
        .name = "coroutine",
        .target = target,
        .optimize = optimize,
    });
    lib.linkLibC();
    lib.linkSystemLibrary("uv");
    lib.defineCMacro("CO_STACK_SIZE", "10240");
    lib.defineCMacro("CO_MAIN_STACK", "11264");
    lib.defineCMacro("CO_SCRAPE_SIZE", "64");
    lib.defineCMacro("HASH_INIT_CAPACITY", "512");
    inline for (coroutine_src_files) |src| {
        lib.addCSourceFile(.{
            .file = .{ .path = src },
            .flags = &.{
                "-std=gnu11",
                "-Wno-return-type",
                "-Wno-int-conversion",
            },
        });
    }
    b.installArtifact(lib);

    const main_tests = b.addTest(.{
        .root_source_file = .{ .path = "src/main.zig" },
        .target = target,
        .optimize = optimize,
    });
    const run_main_tests = b.addRunArtifact(main_tests);
    const test_step = b.step("test", "Run library tests");
    test_step.dependOn(&run_main_tests.step);
}

const coroutine_src_files = [_][]const u8{
    "src/channel.c",
    "src/coroutine.c",
    "src/deferred.c",
    "src/exception.c",
    "src/future.c",
    "src/hash.c",
    "src/raii_allocate.c",
    "src/scheduler.c",
    "src/uv_routine.c",
    "src/uv_url.c",
};
TheTechsTech commented 1 year ago

mingw64? I use Windows daily, simple install, no additional steps, simple prompt lunch, which .cl_32/64.bat in root is for. You can add script PR for mingw64 environment if you want.

I know pthread4w already and use for many other projects.

binarycraft007 commented 1 year ago

@TheTechsTech after commenting out the break in co_uv_listen.c, I got segment fault when connecting it with a client, 100% reproducible, is this the bug you are referring to?

int co_main(int argc, char *argv[]) {
    uv_stream_t *socket = stream_bind("http://127.0.0.1:9010", 0);

    while (true) {
        uv_stream_t *connectedSocket = stream_listen(socket, 1024);
        if (connectedSocket == NULL)
            printf("Invalid handle, got error code: %d\n", co_err_code());

        //break;
        stream_handler(handleClient, connectedSocket);
    }

    return 0;
}
❯ zig-out/bin/co_uv_listen
[1]    43714 segmentation fault (core dumped)  zig-out/bin/co_uv_listen
binarycraft007 commented 1 year ago

mingw64? I use Windows daily, simple install, no additional steps, simple prompt lunch, which .cl_32/64.bat in root is for. You can add script PR for mingw64 environment if you want.

I know pthread4w already and use for many other projects.

yeah, I am add zig build system support for it, it also has a pkg manager, so it can just fetch upstream project source code and compile it, will send an PR once I finished porting.

onderweg commented 1 year ago

return ((values_t *)0)->value; to indicate a NULL union value, that caused segfaults

Ah, good to know. I used return ((values_t *)0)->value; instead of return; as a quick and dirty fix for the compile error, and was wondering if that was a good idea or not.

TheTechsTech commented 1 year ago

@binarycraft007 You should be running in debug mode, I don't see something like:

Thread #7fe9185f1180 running coroutine id: 1 () status: 3
Back at coroutine scheduling
Thread #7fe9185f1180 running coroutine id: 2 () status: 3
Listening to 127.0.0.1:9010 for connections.

The cause could be other issues with Zig.

I initial bought in on there build system, but then I realize how it handles macros will eventually be a problem in the long run on what I am trying to produce.

The output is using macros for debug mode logging only.

TheTechsTech commented 1 year ago

@binarycraft007 also you commented out break; and the whole routine for handling the request not provided.

You actually getting correct behavior but should different error output that shows this library is in complete control.

Coroutine-system, exception during stack unwinding leading to an undefined behavior: sig_segv
    thrown at unknown:0
binarycraft007 commented 1 year ago

@binarycraft007 also you commented out break; and the whole routine for handling the request not provided.

You actually getting correct behavior but should different error output that shows this library is in complete control.

Coroutine-system, exception during stack unwinding leading to an undefined behavior: sig_segv
    thrown at unknown:0

so that means the stream_handler is currently not working? I don't understand why there is a break, isn't the stream_handler code unreachable with the break?

TheTechsTech commented 1 year ago

It's working, but i was just testing the error condition behavior, the program should just had exited in handleClient() when break is removed and no actual connection happened.

You not in debug mode so not sure where your issues is at. I have CO_HERE() macro to track actual flow like this when issues come up.

The script behavior is not complete, the whole integration with libuv is still being worked on.

TheTechsTech commented 1 year ago

I found the segfault your having is in co_handler() then after bug fixing that, and letting the co_uv_listen.c continue execution for a while and then doing "Ctrl-c" the bugs that still needs fixing is:

Listening to 127.0.0.1:9010 for connections.
Received following request: @I

attempt to delete a coroutine that is not dead or suspended
Listening to 127.0.0.1:9010 for connections.
Received following request: y

attempt to delete a coroutine that is not dead or suspended
^Ccoroutine list:
     1  co_main              yield (running) 1
     2                        -1
     5                        -1
     4                        -1
     8                        -1
     7                        -1
    11                        -1
    10                        -1
    14                        -1
    13                        -1
    17                        -1
    16                        -1
    20                        -1
    19                        -1
    23                        -1
    22                        -1
    26                        -1
    25                        -1
    29                        -1
    28                        -1
    32                        -1
    31                        -1
    35                        -1
    34                        -1
    38                        -1
    37                        -1
    41                        -1
    40                        -1
    44                        -1
    43                        -1
    47                        -1
    46                        -1
    50                        -1
    49                        -1
    53                        -1
    52                        -1
    56                        -1
    55                        -1
    59                        -1
    58                        -1
    62                        -1
    61                        1
co_uv_listen: /mnt/c/Users/Lenovo/Documents/c-coroutine/deps/libuv/src/unix/core.c:221: uv_close: Assertion `0' failed.

Coroutine-system, exception during stack unwinding leading to an undefined behavior: sig_abrt
    thrown at unknown:0
TheTechsTech commented 1 year ago

The issues with HTTP handling has been resolved with latest commit, the co_uv_listen.c example works as expected, use create-x509.c to create self signed SSL/TLS certificate.

onderweg commented 1 year ago

Thanks! Orignal error indeed is fixed, although a new error appears:

../c-coroutine/src/strings.c:443:22: error: call to undeclared function 'basename'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    file->basename = basename(file->dirname);
TheTechsTech commented 1 year ago

That function is defined for Windows only. I got error saying declared already error on Linux, it's part of POSIX from what i read, https://man7.org/linux/man-pages/man3/basename.3.html

I guess I need a better check after all.

TheTechsTech commented 1 year ago

I just #include <libgen.h> instead, only defined now for windows.

onderweg commented 1 year ago

Great. Builds now without errors on macOS.