Header-only, event based, tiny and easy to use libuv wrapper in modern C++ - now available as also shared/static library!

Overview

uvw - libuv wrapper in modern C++

Build Status Coverage Documentation Download Gitter chat Donate

Do you have a question that doesn't require you to open an issue? Join the gitter channel.
If you use uvw and you want to say thanks or support the project, please consider becoming a sponsor.
You can help me make the difference. Many thanks to those who supported me and still support me today.

Introduction

uvw started as a header-only, event based, tiny and easy to use wrapper for libuv written in modern C++.
Now it's finally available also as a compilable static library.

The basic idea is to hide completely the C-ish interface of libuv behind a graceful C++ API. Currently, no uv_*_t data structure is actually exposed by the library.
Note that uvw stays true to the API of libuv and it doesn't add anything to its interface. For the same reasons, users of the library must follow the same rules which are used with libuv.
As an example, a handle should be initialized before any other operation and closed once it is no longer in use.

Code Example

#include <uvw.hpp>
#include <memory>

void listen(uvw::Loop &loop) {
    std::shared_ptr<uvw::TCPHandle> tcp = loop.resource<uvw::TCPHandle>();

    tcp->once<uvw::ListenEvent>([](const uvw::ListenEvent &, uvw::TCPHandle &srv) {
        std::shared_ptr<uvw::TCPHandle> client = srv.loop().resource<uvw::TCPHandle>();

        client->on<uvw::CloseEvent>([ptr = srv.shared_from_this()](const uvw::CloseEvent &, uvw::TCPHandle &) { ptr->close(); });
        client->on<uvw::EndEvent>([](const uvw::EndEvent &, uvw::TCPHandle &client) { client.close(); });

        srv.accept(*client);
        client->read();
    });

    tcp->bind("127.0.0.1", 4242);
    tcp->listen();
}

void conn(uvw::Loop &loop) {
    auto tcp = loop.resource<uvw::TCPHandle>();

    tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TCPHandle &) { /* handle errors */ });

    tcp->once<uvw::ConnectEvent>([](const uvw::ConnectEvent &, uvw::TCPHandle &tcp) {
        auto dataWrite = std::unique_ptr<char[]>(new char[2]{ 'b', 'c' });
        tcp.write(std::move(dataWrite), 2);
        tcp.close();
    });

    tcp->connect(std::string{"127.0.0.1"}, 4242);
}

int main() {
    auto loop = uvw::Loop::getDefault();
    listen(*loop);
    conn(*loop);
    loop->run();
}

Motivation

The main reason for which uvw has been written is the fact that there does not exist a valid libuv wrapper in C++. That's all.

Build Instructions

Requirements

To be able to use uvw, users must provide the following system-wide tools:

  • A full-featured compiler that supports at least C++17.
  • libuv (which version depends on the tag of uvw in use).

The requirements below are mandatory to compile the tests and to extract the documentation:

  • CMake version 3.13 or later.
  • Doxygen version 1.8 or later.

Note that libuv is part of the dependencies of the project and may be cloned by CMake in some cases (see below for further details).
Because of that, users don't have to install it to run the tests or when uvw libraries are compiled through CMake.

Library

uvw is a dual-mode library. It can be used in its header-only form or as a compiled static library.
The following sections describe what to do in both cases to get uvw up and runningin your own project.

Header-only

To use uvw as a header-only library, all is needed is to include the uvw.hpp header or one of the other uvw/*.hpp files.
It's a matter of adding the following line at the top of a file:

#include <uvw.hpp>

Then pass the proper -I argument to the compiler to add the src directory to the include paths.
Note that users are required to correctly setup the include directories and libraries search paths for libuv in this case.

When used through CMake, the uvw::uvw target is exported for convenience.

Static

To use uvw as a compiled library, set the BUILD_UVW_LIBS options in cmake before including the project.
This option triggers the generation of a targets named uvw::uvw-static. The matching version of libuv is also compiled and exported as uv::uv-static for convenience.

In case you don't use or don't want to use CMake, you can still compile all .cpp files and include all .h files to get the job done. In this case, users are required to correctly setup the include directories and libraries search paths for libuv.

Versioning

Starting with tag v1.12.0 of libuv, uvw follows the semantic versioning scheme.
The problem is that any version of uvw also requires to track explicitly the version of libuv to which it is bound.
Because of that, the latter wil be appended to the version of uvw. As an example:

vU.V.W_libuv-vX.Y

In particular, the following applies:

  • U.V.W are major, minor and patch versions of uvw.
  • X.Y is the version of libuv to which to refer (where any patch version is valid).

In other terms, tags will look like this from now on:

v1.0.0_libuv-v1.12

Branch master of uvw will be a work in progress branch that follows branch v1.x of libuv (at least as long as it remains their master branch).

Documentation

The documentation is based on doxygen. To build it:

  • $ cd build
  • $ cmake ..
  • $ make docs

The API reference will be created in HTML format within the directory build/docs/html.
To navigate it with your favorite browser:

  • $ cd build
  • $ your_favorite_browser docs/html/index.html

The same version is also available online for the latest release, that is the last stable tag. If you are looking for something more pleasing to the eye, consider reading the nice-looking version available on docsforge: same documentation, much more pleasant to read.

Note

The documentation is mostly inspired by the official libuv API documentation for obvious reasons.

Tests

To compile and run the tests, uvw requires libuv and googletest.
CMake will download and compile both the libraries before compiling anything else.

To build the tests:

  • $ cd build
  • $ cmake .. -DBUILD_TESTING=ON
  • $ make
  • $ ctest -j4 -R uvw

Omit -R uvw if you also want to test libuv and other dependencies.

Crash Course

Vademecum

There is only one rule when using uvw: always initialize the resources and terminate them.

Resources belong mainly to two families: handles and requests.
Handles represent long-lived objects capable of performing certain operations while active.
Requests represent (typically) short-lived operations performed either over a handle or standalone.

The following sections will explain in short what it means to initialize and terminate these kinds of resources.
For more details, please refer to the online documentation.

Handles

Initialization is usually performed under the hood and can be even passed over, as far as handles are created using the Loop::resource member function.
On the other side, handles keep themselves alive until one explicitly closes them. Because of that, memory usage will grow if users simply forget about a handle.
Therefore the rule quickly becomes always close your handles. It's as simple as calling the close member function on them.

Requests

Usually initializing a request object is not required. Anyway, the recommended way to create a request is still through the Loop::resource member function.
Requests will keep themselves alive as long as they are bound to unfinished underlying activities. This means that users don't have to discard a request explicitly .
Therefore the rule quickly becomes feel free to make a request and forget about it. It's as simple as calling a member function on them.

The Loop and the Resource

The first thing to do to use uvw is to create a loop. In case the default one is enough, it's easy as doing this:

auto loop = uvw::Loop::getDefault();

Note that loop objects don't require being closed explicitly, even if they offer the close member function in case a user wants to do that.
Loops can be started using the run member function. The two calls below are equivalent:

loop->run();
loop->run<uvw::Loop::Mode::DEFAULT>();

Available modes are: DEFAULT, ONCE, NOWAIT. Please refer to the documentation of libuv for further details.

In order to create a resource and to bind it to the given loop, just do the following:

auto tcp = loop->resource<uvw::TCPHandle>();

The line above will create and initialize a tcp handle, then a shared pointer to that resource will be returned.
Users should check if pointers have been correctly initialized: in case of errors, they won't be.
Another way to create a resource is:

auto tcp = TCPHandle::create(loop);
tcp->init();

Pretty annoying indeed. Using a loop is the recommended approach.

The resources also accept arbitrary user-data that won't be touched in any case.
Users can set and get them through the data member function as it follows:

resource->data(std::make_shared<int>(42));
std::shared_ptr<void> data = resource->data();

Resources expect a std::shared_pointer<void> and return it, therefore any kind of data is welcome.
Users can explicitly specify a type other than void when calling the data member function:

std::shared_ptr<int> data = resource->data<int>();

Remember from the previous section that a handle will keep itself alive until one invokes the close member function on it.
To know what are the handles that are still alive and bound to a given loop, there exists the walk member function. It returns handles with their types. Therefore, the use of Overloaded is recommended to be able to intercept all types of interest:

handle.loop().walk(uvw::Overloaded{
    [](uvw::TimerHandle &h){ /* application code for timers here */ },
    [](auto &&){ /* ignore all other types */ }
});

This function can also be used for a completely generic approach. For example, all the pending handles can be closed easily as it follows:

loop->walk([](auto &&h){ h.close(); });

No need to keep track of them.

The event-based approach

uvw offers an event-based approach, so resources are small event emitters to which listeners can be attached.
Attaching a listener to a resource is the recommended way to be notified about changes.
Listeners must be callable objects of type void(EventType &, ResourceType &), where:

  • EventType is the type of the event for which they have been designed.
  • ResourceType is the type of the resource that has originated the event.

It means that the following function types are all valid:

  • void(EventType &, ResourceType &)
  • void(const EventType &, ResourceType &)
  • void(EventType &, const ResourceType &)
  • void(const EventType &, const ResourceType &)

Please note that there is no need to keep around references to the resources: they will pass themselves as an argument whenever an event is published.

There exist two methods to attach a listener to a resource:

  • resource.once<EventType>(listener): the listener will be automatically removed after the first event of the given type.
  • resource.on<EventType>(listener): to be used for long-running listeners.

Both of them return an object of type ResourceType::Connection (as an example, TCPHandle::Connection).
A connection object can be used later as an argument to the erase member function of the resource to remove the listener.
There exists also the clear member function to drop all the listeners at once. Note that clear should only be invoked on non-active handles. The handles exploit the same event mechanism made available to users to satisfy pending requests. Invoking clear on an active handle, for example with requests still in progress, risks leading to memory leaks or unexpected behavior.

Almost all the resources emit ErrorEvent in case of errors.
All the other events are specific for the given resource and documented in the API reference.

The code below shows how to create a simple tcp server using uvw:

auto loop = uvw::Loop::getDefault();
auto tcp = loop->resource<uvw::TCPHandle>();

tcp->on<uvw::ErrorEvent>([](const uvw::ErrorEvent &, uvw::TCPHandle &) { /* something went wrong */ });

tcp->on<uvw::ListenEvent>([](const uvw::ListenEvent &, uvw::TCPHandle &srv) {
    std::shared_ptr<uvw::TCPHandle> client = srv.loop().resource<uvw::TCPHandle>();
    client->once<uvw::EndEvent>([](const uvw::EndEvent &, uvw::TCPHandle &client) { client.close(); });
    client->on<uvw::DataEvent>([](const uvw::DataEvent &, uvw::TCPHandle &) { /* data received */ });
    srv.accept(*client);
    client->read();
});

tcp->bind("127.0.0.1", 4242);
tcp->listen();

Note also that uvw::TCPHandle already supports IPv6 out-of-the-box. The statement above is equivalent to tcp->bind<uvw::IPv4>("127.0.0.1", 4242).
It's sufficient to explicitly specify uvw::IPv6 as the underlying protocol to use it.

The API reference is the recommended documentation for further details about resources and their methods.

Going raw

In case users need to use functionalities not wrapped yet by uvw or if they want to get the underlying data structures as defined by libuv for some other reasons, almost all the classes in uvw give direct access to them.
Please, note that this functions should not be used directly unless users know exactly what they are doing and what are the risks. Going raw is dangerous, mainly because the lifetime management of a loop, a handle or a request is completely controlled by the library and working around it could quickly break things.

That being said, going raw is a matter of using the raw member functions:

auto loop = uvw::Loop::getDefault();
auto tcp = loop->resource<uvw::TCPHandle>();

uv_loop_t *raw = loop->raw();
uv_tcp_t *handle = tcp->raw();

Go the raw way at your own risk, but do not expect any support in case of bugs.

Contributors

If you want to contribute, please send patches as pull requests against the branch master.
Check the contributors list to see who has partecipated so far.

License

Code and documentation Copyright (c) 2016-2021 Michele Caini.
Logo Copyright (c) 2018-2021 Richard Caseres.

Code released under the MIT license. Documentation released under CC BY 4.0.
Logo released under CC BY-SA 4.0.

Support

If you want to support this project, you can offer me an espresso.
If you find that it's not enough, feel free to help me the way you prefer.

Comments
  • BUILD_UVW_LIBS doesn't work on Windows (no symbols are exported)

    BUILD_UVW_LIBS doesn't work on Windows (no symbols are exported)

    Hi,

    When building UVW as a shared library (by setting BUILD_UVW_LIBS to ON) on Windows, a DLL is created but without any .lib file. The issue is that nothing is exported using__declspec(dllexport).

    I suggest to make the same thing as libuv, that is: https://github.com/libuv/libuv/blob/36549815eed297c74448ff580b5c84713245ec5d/include/uv.h#L30

    And putting the equivalent of UV_EXTERN to classes and functions. This would allow to use -fvisibility=hidden with gcc too.

    Are you willing to support that ?

    Thanks :)

    build system static-shared-libs 
    opened by amurzeau 51
  • Support dynamic linkage of tests

    Support dynamic linkage of tests

    If libuv is not fetched, try to find and provide libuv parameters using pkg-config. Makes dynamic linking to shared libuv library from the system.

    Expects just default header-included mode. It should be possible to link dynamically to libuv also on built libraries. I don't think it is possible now. But since even shared build does not have library versioning, I am not sure it is ready for Linux distributions in that mode.

    build system 
    opened by pemensik 36
  • Need help using uvw together with boost::coroutines2

    Need help using uvw together with boost::coroutines2

    I don't know where to ask. So I ended up with submitting an issue here. I'm new to libuv & uvw. I'm trying to apply async-await pattern to libuv, so I tried using uvw together with boost::coroutines2.

    template<typename EventType, typename EmitterType>
    EventType awaitEvent(std::shared_ptr<uvw::Loop>& loop, std::shared_ptr<EmitterType>& emitter) {
        using coro_t = boost::coroutines2::coroutine<EventType>;
        
        typename coro_t::pull_type source([&](typename coro_t::push_type& sink) {
            typename EmitterType::template Connection<EventType> ok;
            auto err = emitter->template once<uvw::ErrorEvent>([&](uvw::ErrorEvent &error, auto&) {
                emitter->template erase(ok);
                throw error;
            });
            ok = emitter->template once<EventType>([&](EventType& event, auto&) {
                emitter->template erase(err);
                sink(std::move(event));
            });
            loop->run<uvw::Loop::Mode::ONCE>();
        });
        auto result = std::move(source().get());
        source();
        return result;
    }
    

    To use it:

    auto fileReq = loop->resource<FileReq>();
    
    fileReq->open(path + "/" + event.filename, Flags<FileReq::FileOpen>(FileReq::FileOpen::RDONLY), S_IRUSR);
    
    awaitEvent<FsEvent<FsReq::Type::OPEN>>(loop, fileReq);
    
    fileReq->stat();
    const auto fileSize = awaitEvent<FsEvent<FsReq::Type::STAT>>(loop, fileReq).stat.st_size;
    

    The program always crashes at the second awaitEvent because loop->run<uvw::Loop::Mode::ONCE>(); won't wait for next fs_event. If I changes the line to loop->run();, the program hangs forever.

    I know it's not a good place to ask libuv usage, but I don't know where to ask. Please help. This is the full code(crashes at line 27) if needed.

    Thanks in advance.

    question 
    opened by CarterLi 28
  • conversion from void* to the pointer of the base class is not a good idea

    conversion from void* to the pointer of the base class is not a good idea

    https://github.com/skypjack/uvw/blob/a10844d4bfd1e31bd062af9aae65add0e70cc136/src/uvw/resource.hpp#L44

    https://github.com/skypjack/uvw/blob/a10844d4bfd1e31bd062af9aae65add0e70cc136/src/uvw/loop.cpp#L113

    basehandle::type() in uv_walk which is in a timer callback still causes an undefined behavior.

    On windows, BaseHandleWalk test failed. 图片

    Related issue: https://github.com/skypjack/uvw/issues/212

    Reference: https://stackoverflow.com/a/5445220

    bug 
    opened by darsvador 22
  • Logo

    Logo

    Hi all,

    I just realized that we don't have a logo for uvw yet. :-) It would be great if someone wanted to suggest something or make a contribution directly with an image. Thank you very much for your help!!

    help wanted 
    opened by skypjack 21
  • Common create method

    Common create method

    The advantage of having a common create method is that it consolidates the dynamic allocation of "resources" in uvw. This doesn't exhaust all instances, but reduces the usage of new in existing code. An observable benefit of the change is the reduction of duplicate arguments to the create method and the class constructors.

    Change description: Consolidate the <Type>::create methods from various classes - SharedLib, Thread and others in a single base class. Also aggregate other similar functionality like getting the owning Loop object reference, getting the owned libuv structure pointer. Since class Resource inherits Emitter and std::enable_shared_from_this, it isn't a feasible option. Therefore, ResourceBase (the name can be decided upon) is extracted from and inherited into Resource. This essentially means no API change in the final classes of uvw.

    opened by tusharpm 21
  • Internal compiler error

    Internal compiler error

    Hi,

    When build on a fresh ubuntu 16.04 that uses gcc 5.4.0, compiler crashes with the following:

    uvw/src/uvw/process.hpp:235:49: internal compiler error: in tsubst_copy, at cp/pt.c:13217
             container.data.stream = get<uv_stream_t>(stream);
                                                     ^
    Please submit a full bug report,
    with preprocessed source if appropriate.
    

    Any ideas on this one?

    opened by raoulh 21
  • Build error with vs2019

    Build error with vs2019

    I try to use v1.16.0_libuv-v1.28 release on Visual Studio 2019, and I got following errors: image Here are part of the compiler output:

    1>------ Build started: Project: Server, Configuration: Debug x64 ------
    1>pch.cpp
    1>C:\source\Server\include\uvw\lib.hpp(68,1): error C3537:  you cannot cast to a type that contains 'auto'
    1>C:\source\Server\include\uvw\lib.hpp(68,1): message :  This diagnostic occurred in the compiler generated function 'F *uvw::SharedLib::sym(std::string)'
    1>C:\source\Server\include\uvw\lib.hpp(68,1): error C2100:  illegal indirection
    1>C:\source\Server\include\uvw\lib.hpp(68,1): message :  This diagnostic occurred in the compiler generated function 'F *uvw::SharedLib::sym(std::string)'
    1>C:\source\Server\include\uvw\thread.hpp(109,36): warning C4838:  conversion from 'uvw::Flags<uvw::Thread::Options>' to 'unsigned int' requires a narrowing conversion
    1>C:\source\Server\include\uvw\thread.hpp(165,1): error C3537:  you cannot cast to a type that contains 'auto'
    1>C:\source\Server\include\uvw\thread.hpp(165,1): message :  This diagnostic occurred in the compiler generated function 'T *uvw::ThreadLocalStorage::get(void) noexcept'
    1>C:\source\Server\include\uvw\thread.hpp(165,1): error C2100:  illegal indirection
    

    My cl.exe version is Microsoft (R) C/C++ Optimizing Compiler Version 19.21.27619.1 for x64

    wontfix 
    opened by Gaojianli 19
  • + improve CMake-based package config files.

    + improve CMake-based package config files.

    • CMake package config files for uvw, they are now installed as ${LIBDIR}/cmake/uvw/uvwConfig.cmake with target files for appropriate configuration (e.g. debug, release, etc...).

    • A uvw::uvw ALIAS target is created for uvw static library, to make persistency with what is done to the header-only version,

    Callers can now use find_package(uvw) and link with the uvw::uvw target to use uvw in their projects directly using CMake.

    build system 
    opened by moodyhunter 17
  • #135 Conan package support

    #135 Conan package support

    Hi!

    This PR brings the support for Conan.

    Including:

    • .conan/build.py Build script to create Conan package on Travis CI
    • .conan/test_package/CMakeLists.txt CMake file to build test package
    • .conan/test_package/conanfile.py Conan recipe to build test package
    • .conan/test_package/test_package.cpp Example code to consume Conan package created
    • .travis.yml Update to run Conan job on CI
    • conanfile.py Conan recipe to provide UVM package
    • bintray badge on README Download link page for UVM package

    Conan uses the file conanfile.py as recipe to execute all steps necessary to create the package. As your project is header-only it doesn't need build anything, just copy all headers and license. Conan defines the package id by settings + options and UVW is header-only so it doesn't need set anything.

    To make sure that your package is working well, Conan provides test_package, where we put a simple example consuming your package and building as well. When test_package.cpp is including uvw header, all files are imported from the packaged provided by Conan. Test package is not for unit testing propose, it's a package validation.

    When running your package on CI (appveyor, travis or any other) we could run Conan to create the package and check. But prepare a full environment with compiler, build-essential , conan and all stuff could be boring, so we use Docker. Conan provides a good range of images, including gcc and clang. Here I added only GCC 8 because we only need to create a package for any architecture or OS -- header-only project doesn't provide binaries by platform.

    How to upload?

    Conan uses Bintray to store their packages. You need to create an account on bintray for that. There is a good documentation how to create a bintray account here.

    The build.py is configured following the reference skypjack/conan/uvw/. Where:

    • skypjack is your Bintray user name
    • conan is the repository name
    • uvw is the package name

    Both username and repository you will need to set manually on web interface. Both username and repository could be changed by your preference, I just followed the convention.

    Also, build.py has a rule to upload only tags or any branch with the pattern name "v\d+.\d+.\d+.*".

    And finally, you must set the variable CONAN_PASSWORD on Travis settings. The password is the Bintray API Key, not your account password. To read your API key you need to access https://bintray.com/profile/edit and click on API Key button. Don't forget to mark as secret on Travis settings.

    After to upload your package by CI, we recommend update the Bintray package page: https://bintray.com/skypjack/conan/uvw%3Askypjack/edit?tab=general The page contains only project metadata, as url, maturity (official), license -- There is a field for package avatar, you could use conan-uvw logo with you prefer or uvw official.

    Okay, this is a lot of information. Please, feel free to ask anything.

    I included @danimtb to review this PR. He is a Conan expert and maintainer.

    Regards!

    /cc @danimtb

    closes #135

    enhancement build system 
    opened by uilianries 17
  • Assert in libuv

    Assert in libuv

    Hi,

    I have a strange bug, and don't know if it's in uvw, libuv or my own code. I will explain here and maybe someone has any hints.

    I have an Idle handle that start a process at some point. It works and at some random point in time my my code crashes with an assert exactly when the process is launched:

    [INF] lua (ScriptExec.cpp:39) Starting script. (0xd7b480)
    [INF] process (ExternProc.cpp:191) Starting process: /usr/bin/calaos_script --socket /tmp/calaos_proc_c79ad522-33ff-978a-3d31-08070a51c459_lua_21499 --namespace lua
    calaos_server: ../libuv-1.19.1/src/unix/stream.c:1574: uv_read_start: Assertion `uv__stream_fd(stream) >= 0' failed.
    

    What my code does is basically easy:

    • it create a uvw::ProcessHandle
    • setup uvw::ExitEvent and uvw::ErrorEvent for the process handle
    • then create a uvw::PipeHandle for communicating with the process
    • setup uvw::EndEvent and uvw::DataEvent for the pipe
    • spawn the process
    • start pipe->read() (aka. uv_read_start())

    Full code of the function is here: https://github.com/calaos/calaos_base/blob/master/src/bin/calaos_server/IO/ExternProc.cpp#L147

    It works. Sometime it works for a long time (hours). And then it crashes with this backtrace:

    Program received signal SIGABRT, Aborted.
    __GI_raise (sig=sig@entry=6) at /usr/src/debug/glibc/2.25-r0/git/sysdeps/unix/sysv/linux/raise.c:51
    51      }
    (gdb) bt
    #0  __GI_raise (sig=sig@entry=6) at /usr/src/debug/glibc/2.25-r0/git/sysdeps/unix/sysv/linux/raise.c:51
    #1  0x000000310e23450a in __GI_abort () at /usr/src/debug/glibc/2.25-r0/git/stdlib/abort.c:89
    #2  0x000000310e22bfe7 in __assert_fail_base (fmt=<optimized out>, assertion=assertion@entry=0x7ffff7deaca6 "uv__stream_fd(stream) >= 0",
        file=file@entry=0x7ffff7dea998 "../libuv-1.19.1/src/unix/stream.c", line=line@entry=1574, function=function@entry=0x7ffff7deae48 <__PRETTY_FUNCTION__.9160> "uv_read_start")
        at /usr/src/debug/glibc/2.25-r0/git/assert/assert.c:92
    #3  0x000000310e22c092 in __GI___assert_fail (assertion=assertion@entry=0x7ffff7deaca6 "uv__stream_fd(stream) >= 0",
        file=file@entry=0x7ffff7dea998 "../libuv-1.19.1/src/unix/stream.c", line=line@entry=1574, function=function@entry=0x7ffff7deae48 <__PRETTY_FUNCTION__.9160> "uv_read_start")
        at /usr/src/debug/glibc/2.25-r0/git/assert/assert.c:101
    #4  0x00007ffff7de316d in uv_read_start (stream=stream@entry=0xd8b418,
        alloc_cb=alloc_cb@entry=0x48ffe0 <uvw::Handle<uvw::PipeHandle, uv_pipe_s>::allocCallback(uv_handle_s*, unsigned long, uv_buf_t*)>,
        read_cb=read_cb@entry=0x498320 <uvw::StreamHandle<uvw::PipeHandle, uv_pipe_s>::readCallback(uv_stream_s*, long, uv_buf_t const*)>)
        at /usr/src/debug/libuv/1.19.1-r0/libuv-1.19.1/src/unix/stream.c:1574
    #5  0x0000000000497bf9 in uvw::Handle<uvw::PipeHandle, uv_pipe_s>::invoke<int (*)(uv_stream_s*, void (*)(uv_handle_s*, unsigned long, uv_buf_t*), void (*)(uv_stream_s*, long, uv_buf_t const*)), uv_stream_s*, void (*)(uv_handle_s*, unsigned long, uv_buf_t*), void (*)(uv_stream_s*, long, uv_buf_t const*)>(int (*&&)(uv_stream_s*, void (*)(uv_handle_s*, unsigned long, uv_buf_t*), void (*)(uv_stream_s*, long, uv_buf_t const*)), uv_stream_s*&&, void (*&&)(uv_handle_s*, unsigned long, uv_buf_t*), void (*&&)(uv_stream_s*, long, uv_buf_t const*)) (f=<optimized out>, this=0xd8b3b0) at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/lib/uvw/src/uvw/handle.hpp:62
    #6  uvw::StreamHandle<uvw::PipeHandle, uv_pipe_s>::read (this=0xd8b3b0)
        at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/lib/uvw/src/uvw/stream.hpp:228
    #7  ExternProcServer::startProcess (this=0xd7b480, process=..., name=..., args=...)
        at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/bin/calaos_server/IO/ExternProc.cpp:193
    #8  0x000000000062b8f3 in ScriptExec::ExecuteScriptDetached(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<void (bool)>, Params) (script=..., cb=..., env=...) at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/bin/calaos_server/LuaScript/ScriptExec.cpp:150
    #9  0x000000000063c021 in Calaos::ActionScript::Execute (this=<optimized out>)
        at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/bin/calaos_server/Rules/ActionScript.cpp:39
    #10 0x00000000006358f1 in Calaos::Rule::ExecuteActions (this=0xc441f0)
        at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/bin/calaos_server/Rule.cpp:148
    #11 0x0000000000626eae in Calaos::ListeRule::ExecuteRuleSignal (this=this@entry=0x977980 <Calaos::ListeRule::Instance()::inst>, id=...)
        at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/bin/calaos_server/ListeRule.cpp:182
    #12 0x00000000006241ce in Calaos::ListeRule::<lambda()>::operator() (__closure=0xd8b660)
        at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/bin/calaos_server/ListeRule.cpp:101
    #13 sigc::adaptor_functor<Calaos::ListeRule::ExecuteRuleSignal(std::__cxx11::string)::<lambda()> >::operator() (this=0xd8b660)
        at /usr/include/sigc++-2.0/sigc++/adaptors/adaptor_trait.h:256
    #14 sigc::internal::slot_call0<Calaos::ListeRule::ExecuteRuleSignal(std::__cxx11::string)::<lambda()>, void>::call_it(sigc::internal::slot_rep *) (rep=0xd8b630)
        at /usr/include/sigc++-2.0/sigc++/functors/slot.h:114
    #15 0x0000000000670602 in sigc::slot0<void>::operator() (this=0xd8b608) at /usr/include/sigc++-2.0/sigc++/functors/slot.h:513
    #16 Idler::<lambda()>::operator() (__closure=0xd8b608) at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/lib/Timer.cpp:136
    #17 sigc::adaptor_functor<Idler::singleIdler(sigc::slot<void>)::<lambda()> >::operator() (this=0xd8b600) at /usr/include/sigc++-2.0/sigc++/adaptors/adaptor_trait.h:256
    #18 sigc::internal::slot_call<Idler::singleIdler(sigc::slot<void>)::<lambda()>, void>::call_it(sigc::internal::slot_rep *) (rep=0xd8b5d0)
        at /usr/include/sigc++-2.0/sigc++/functors/slot.h:461
    #19 0x000000000066f84a in sigc::internal::signal_emit0<void, sigc::nil>::emit (impl=0xd6ef20) at /usr/include/sigc++-2.0/sigc++/signal.h:794
    #20 sigc::signal0<void, sigc::nil>::emit (this=<optimized out>) at /usr/include/sigc++-2.0/sigc++/signal.h:2800
    #21 Idler::<lambda(const auto:32&, auto:33&)>::operator()<uvw::IdleEvent, uvw::IdleHandle> (__closure=<optimized out>)
        at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/lib/Timer.cpp:125
    #22 std::_Function_handler<void(uvw::IdleEvent&, uvw::IdleHandle&), Idler::createIdler()::<lambda(const auto:32&, auto:33&)> >::_M_invoke(const std::_Any_data &, uvw::IdleEvent &, uvw::IdleHandle &) (__functor=..., __args#0=..., __args#1=...) at /usr/include/c++/6.3.0/functional:1731
    #23 0x000000000066f95e in std::function<void (uvw::IdleEvent&, uvw::IdleHandle&)>::operator()(uvw::IdleEvent&, uvw::IdleHandle&) const (__args#1=..., __args#0=...,
        this=<optimized out>) at /usr/include/c++/6.3.0/functional:2127
    #24 _ZZN3uvw7EmitterINS_10IdleHandleEE7HandlerINS_9IdleEventEE7publishES4_RS1_ENKUlOT_E_clIRSt4pairIbSt8functionIFvRS4_S6_EEEEEDaS8_ (element=..., __closure=<synthetic pointer>)
        at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/lib/uvw/src/uvw/emitter.hpp:118
    #25 _ZSt8for_eachISt16reverse_iteratorISt14_List_iteratorISt4pairIbSt8functionIFvRN3uvw9IdleEventERNS4_10IdleHandleEEEEEEZNS4_7EmitterIS7_E7HandlerIS5_E7publishES5_S8_EUlOT_E_ET0_SI_SI_SL_ (__first=..., __last=..., __f=...) at /usr/include/c++/6.3.0/bits/stl_algo.h:3769
    #26 0x000000000066fedd in uvw::Emitter<uvw::IdleHandle>::Handler<uvw::IdleEvent>::publish (ref=..., event=..., this=<optimized out>)
        at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/lib/uvw/src/uvw/emitter.hpp:123
    #27 uvw::Emitter<uvw::IdleHandle>::publish<uvw::IdleEvent> (this=0xd8b268, event=...)
        at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/lib/uvw/src/uvw/emitter.hpp:166
    #28 uvw::IdleHandle::startCallback (handle=<optimized out>) at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/lib/uvw/src/uvw/idle.hpp:40
    #29 0x00007ffff7dde3c4 in uv__run_idle (loop=loop@entry=0x7ffff7ff2cc0 <default_loop_struct>) at /usr/src/debug/libuv/1.19.1-r0/libuv-1.19.1/src/unix/loop-watcher.c:68
    #30 0x00007ffff7dd8175 in uv_run (loop=0x7ffff7ff2cc0 <default_loop_struct>, mode=mode@entry=UV_RUN_DEFAULT) at /usr/src/debug/libuv/1.19.1-r0/libuv-1.19.1/src/unix/core.c:361
    #31 0x0000000000413e99 in uvw::Loop::run<(uvw::details::UVRunMode)0> (this=<optimized out>)
        at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/lib/uvw/src/uvw/loop.hpp:284
    #32 main (argc=<optimized out>, argv=<optimized out>) at /usr/src/debug/calaos-server/1_3.0-rc1+r0+gitAUTOINC+19f8b098fd-r0/git/src/bin/calaos_server/main.cpp:185
    

    When inspecting the stream->io_watcher.fd it is -1. So the assert is correct that the uv_read cannot start- But why is this sometime -1... I really don't know...

    (gdb) p *stream
    $1 = {data = 0xd8b3b0, loop = 0x7ffff7ff2cc0 <default_loop_struct>, type = UV_NAMED_PIPE, close_cb = 0x0, handle_queue = {0xd88488, 0xd8bb78}, u = {fd = 0, reserved = {0x0,
          0x0, 0x0, 0x0}}, next_closing = 0x0, flags = 8196, write_queue_size = 0, alloc_cb = 0x0, read_cb = 0x0, connect_req = 0x0, shutdown_req = 0x0, io_watcher = {
        cb = 0x7ffff7de2170 <uv__stream_io>, pending_queue = {0xd8b4a8, 0xd8b4a8}, watcher_queue = {0xd8b4b8, 0xd8b4b8}, pevents = 0, events = 0, fd = -1}, write_queue = {0xd8b4d8,
        0xd8b4d8}, write_completed_queue = {0xd8b4e8, 0xd8b4e8}, connection_cb = 0x0, delayed_error = 0, accepted_fd = -1, queued_fds = 0x0}
    

    My question here is: do I need to setup something or check something prior starting pipe->read() ? Is it a bug in libuv? uvw?

    Thank you very much for any pointer.

    invalid 
    opened by raoulh 17
  • I need the way to set buffer when I read from stream

    I need the way to set buffer when I read from stream

    In stream like things, I need to collect several data events to make full packet. but it seems there are lack of interface I can give my buffer data(aka. char[]) when I read from stream.

    Because uvw stands for thin wrapper of libuv, I think it should be possible.

    Current implementation allocates by uvw in Handle::allocCallback

    It seems when I write I have controls of buffer but when I read it seems not.

    If i can set this kind of call back to streams I could control it. auto alloc_callback(Handle<T, U>& handle, std::size_t suggested) -> char*

    I don't want allocation happens in every read operation.

    triage 
    opened by hihig2001 4
  • Add static lib when building with system's static libuv

    Add static lib when building with system's static libuv

    When building with -DFETCH_LIBUV=OFF, -DFIND_LIBUV=ON and -DBUILD_UVW_LIBS=ON and a static build of libuv, the build fails with the following error:

    -- Checking for module 'libuv>=1.44.1'
    --   Found libuv, version 1.44.1
    -- libuv 1.44.1 found via pkg-config
    -- Configuring done
    CMake Error at src/CMakeLists.txt:76 (target_link_libraries):
    -- Generating done
      Target "uvw" links to:
    
        uv::uv-static
    
    
      but the target was not found.  Possible reasons include:
    
        * There is a typo in the target name.
        * A find_package call is missing for an IMPORTED target.
        * An ALIAS target is missing.
    

    This can be fixed by adding the uv-static target when building uvw as a static library.

    triage 
    opened by darktohka 9
  • UVW v3

    UVW v3

    A breaking change to set a tipping point for a new version of uvw, an updated coding style (with a more standard-ish snake style) and huge performance improvements during compilation. Feedback are highly appreciated. 🙂

    enhancement help wanted discussion 
    opened by skypjack 7
  • UDP send after connect not possible

    UDP send after connect not possible

    Once a UDP socket is connected in libuv, you have to call send with a null address or else you get UV_EISCONN and nothing is sent. There seems to be no way to do this through the uvw API, since the addr parameter is passed by reference. In udp.cc the wrappers are like:

    UVW_INLINE void UDPHandle::send(const sockaddr &addr, std::unique_ptr<char[]> data, unsigned int len) {
    ...
        req->send(get(), &addr);
    }
    

    Empirically it works to call it like

       sock->send(*(sockaddr *)nullptr, txbuf, txbuf_size);
    

    But this is undefined behavior in C++, and the compiler (at least Clang++-10) warns accordingly.

    I think the right answer is to have versions of UDPHandle::send that don't take an address parameter.

    References: http://docs.libuv.org/en/v1.x/udp.html in the uv_udp_send section

    enhancement 
    opened by tlbtlbtlb 1
  • Failures in unit tests on some platforms

    Failures in unit tests on some platforms

    Hi, I have attempted to prepare a RPM Fedora package of this library. I enabled building of tests. My test build failed on few platforms: armv7hl s390x ppc64le. But it passed fine on more common platforms: i686 x86_64 aarch64.

    Temporary build link (would be gone in few days): https://koji.fedoraproject.org/koji/taskinfo?taskID=74293472

    + cd uvw-2.9.0_libuv_v1.41
    + cd redhat-linux-build
    + /usr/bin/ctest --output-on-failure --force-new-ctest-process -j5
    Test project /builddir/build/BUILD/uvw-2.9.0_libuv_v1.41/redhat-linux-build
          Start  1: uvw_main
          Start  2: uvw_async
          Start  3: uvw_check
          Start  4: uvw_emitter
          Start  5: uvw_file_req
     1/28 Test  #1: uvw_main .........................   Passed    0.01 sec
          Start  6: uvw_fs_event
     2/28 Test  #2: uvw_async ........................   Passed    0.01 sec
          Start  7: uvw_fs_poll
     3/28 Test  #3: uvw_check ........................   Passed    0.01 sec
          Start  8: uvw_fs_req
     4/28 Test  #4: uvw_emitter ......................   Passed    0.01 sec
          Start  9: uvw_handle
     5/28 Test  #6: uvw_fs_event .....................   Passed    0.01 sec
          Start 10: uvw_idle
     6/28 Test  #9: uvw_handle .......................   Passed    0.01 sec
          Start 11: uvw_lib
     7/28 Test #10: uvw_idle .........................   Passed    0.01 sec
          Start 12: uvw_loop
     8/28 Test  #5: uvw_file_req .....................   Passed    0.02 sec
          Start 13: uvw_pipe
     9/28 Test  #8: uvw_fs_req .......................   Passed    0.02 sec
          Start 14: uvw_prepare
    10/28 Test #11: uvw_lib ..........................   Passed    0.01 sec
          Start 15: uvw_process
    11/28 Test #12: uvw_loop .........................   Passed    0.01 sec
          Start 16: uvw_request
    12/28 Test #13: uvw_pipe .........................   Passed    0.01 sec
          Start 17: uvw_resource
    13/28 Test #14: uvw_prepare ......................   Passed    0.01 sec
          Start 18: uvw_signal
    14/28 Test #15: uvw_process ......................   Passed    0.01 sec
          Start 19: uvw_stream
    15/28 Test #16: uvw_request ......................   Passed    0.01 sec
          Start 20: uvw_tcp
    16/28 Test #17: uvw_resource .....................   Passed    0.01 sec
          Start 21: uvw_thread
    17/28 Test #18: uvw_signal .......................   Passed    0.01 sec
          Start 22: uvw_timer
    18/28 Test #19: uvw_stream .......................   Passed    0.01 sec
          Start 23: uvw_tty
    19/28 Test #20: uvw_tcp ..........................   Passed    0.01 sec
          Start 24: uvw_udp
    20/28 Test #21: uvw_thread .......................   Passed    0.01 sec
          Start 25: uvw_underlying_type
    21/28 Test #23: uvw_tty ..........................   Passed    0.01 sec
          Start 26: uvw_util
    22/28 Test #24: uvw_udp ..........................   Passed    0.01 sec
          Start 27: uvw_work
    23/28 Test #25: uvw_underlying_type ..............   Passed    0.01 sec
          Start 28: uvw_file_req_sendfile
    24/28 Test #26: uvw_util .........................***Failed    0.01 sec
    Running main() from /builddir/build/BUILD/googletest-release-1.10.0/googletest/src/gtest_main.cc
    24/28 Test #26: uvw_util .........................***Failed    0.01 sec
    Running main() from /builddir/build/BUILD/googletest-release-1.10.0/googletest/src/gtest_main.cc
    [==========] Running 3 tests from 1 test suite.
    [----------] Global test environment set-up.
    [----------] 3 tests from Util
    [ RUN      ] Util.UnscopedFlags
    [       OK ] Util.UnscopedFlags (0 ms)
    [ RUN      ] Util.ScopedFlags
    [       OK ] Util.ScopedFlags (0 ms)
    [ RUN      ] Util.Utilities
    /builddir/build/BUILD/uvw-2.9.0_libuv_v1.41/test/uvw/util.cpp:128: Failure
    Expected: (cpuInfo[0].speed) != (decltype(cpuInfo[0].speed){0}), actual: 0 vs 0
    [  FAILED  ] Util.Utilities (1 ms)
    [----------] 3 tests from Util (2 ms total)
    [----------] Global test environment tear-down
    [==========] 3 tests from 1 test suite ran. (2 ms total)
    [  PASSED  ] 2 tests.
    [  FAILED  ] 1 test, listed below:
    [  FAILED  ] Util.Utilities
    
     1 FAILED TEST
    

    Would you know if it needs fixing? Should be speed always non-zero?

    triage 
    opened by pemensik 4
Owner
Michele Caini
I'm a freelancer and a senior software engineer. What else?
Michele Caini
modern c++(c++17), cross-platform, header-only, easy to use http framework

cinatra--一个高效易用的c++ http框架 English | 中文 目录 使用cinatra常见问题汇总(FAQ) cinatra简介 如何使用 快速示例 性能测试 注意事项 roadmap 联系方式 cinatra简介 cinatra是一个高性能易用的http框架,它是用modern

qicosmos 1.4k Dec 30, 2022
An SFTP client shared library (dll/so/dylib) with bindings and classes for C++, Delphi and Free Pascal based on PuTTY

TGPuttyLib A shared library / DLL with Delphi and C++ bindings based on PuTTY, for Windows, macOS, and Linux. The new TGPuttyLib SFTP Library is a DLL

Tobias Giesen 74 Dec 19, 2022
WinINet wrapper - tiny windows HTTPS library, no dependencies.

WNetWrap A tiny, dependency-free wrapper around WinINet for developers targeting Windows only, who need a lightweight native solution. Inspired by the

hack-tramp 26 Nov 4, 2022
A simple tcp tunnel on c using sockets Right now it only supports linux systems

A simple tcp tunnel on c using sockets Right now it only supports linux systems build BY MAKE mkdir build make cd build ./tunnel.o <localport> <rem

notaweeb 8 Sep 20, 2021
modern C++(C++11), simple, easy to use rpc framework

modern C++(C++11), simple, easy to use rpc framework

qicosmos 1.2k Jan 4, 2023
A software C library designed to extract data attributes from network packets, server logs, and from structured events in general, in order to make them available for analysis

MMT-DPI A software C library desinged to extract data attributes from network packets, server logs, and from structured events in general, in odrder t

Montimage 3 Nov 9, 2022
BingBing 60 Dec 15, 2022
Event-driven network library for multi-threaded Linux server in C++11

Muduo is a multithreaded C++ network library based on the reactor pattern. http://github.com/chenshuo/muduo Copyright (c) 2010, Shuo Chen. All righ

Shuo Chen 12.4k Jan 1, 2023
Lightweight, header-only, Boost-based socket pool library

Stream-client This is a lightweight, header-only, Boost-based library providing client-side network primitives to easily organize and implement data t

Tinkoff.ru 12 Aug 5, 2022
Tiny HTTP Server on C, using only standard libraries

hell_o Linux only. Tiny HTTP Server on C, using only standard libraries. It is unfinished yet, going to add working interface and rewrite handler late

null 3 Feb 1, 2022
An easy to use and powerful open source websocket library written in C.

libwebsock Easy to use C library for websockets This library allows for quick and easy development of applications that use the websocket protocol, wi

Jonathan Hall 47 Nov 13, 2022
A high-performance and easy-to-use C++ network library.

pine A high-performance and easy-to-use C++ network library. Now this is just a toy library for education purpose, do not use in production. example A

Baroquer 80 Dec 30, 2022
Easy-to-use HTTP C library

LibHTTP LibHTTP is a C library easy-to-use which implements the base of the HTTP protocol. Info's about LibHTTP LibHTTP is an easy-to-use HTTP library

null 6 Dec 10, 2021
Now get your alerts & updates about home, wherever you are, with an SMS on your mobile! All with a simple NodeMCU project!

Now get your alerts & updates about home, wherever you are, with an SMS on your mobile! All with a simple NodeMCU project!

Priyanka Peddinti 2 Oct 20, 2021
Event loop friendly C++ actor micro-framework

Rotor rotor is event loop friendly C++ actor micro framework, github gitee features minimalistic loop agnostic core erlang-like hierarchical superviso

Ivan Baidakou 230 Dec 7, 2022
Full-featured high-performance event loop loosely modelled after libevent

libev is a high-performance event loop/event model with lots of features. (see benchmark at http://libev.schmorp.de/bench.html) ABOUT Homepage:

Paul Bohm 1.4k Jan 3, 2023
T-Watch 2020 v1 compatible firmware providing WiFi and BLE testing tools (and also, a watch :D)

ESP-IDF template app This is a template application to be used with Espressif IoT Development Framework. Please check ESP-IDF docs for getting started

Damien Cauquil 49 Dec 23, 2022
A Fast and Easy to use microframework for the web.

A Fast and Easy to use microframework for the web. Description Crow is a C++ microframework for running web services. It uses routing similar to Pytho

Crow 1.4k Jan 4, 2023