Git Product home page Git Product logo

epollcoroutinedoctest's Introduction

C++ Socket server epool coroutines (c++20)

  • Sources, headers and mains separated in distinct folders
  • Use of modern CMake for much easier compiling
  • Setup for tests using doctest
  • Code coverage reports (TODO:review this) including automatic upload to Coveralls.io and/or Codecov.io
  • Code documentation with Doxygen

Requirements

doxygen lcov build-essential gdb cmake

sudo apt install doxygen lcov build-essential gdb cmake

Structure

You can find main executable in app/main.cc under the Build section in CMakeLists.txt.

Building, Testing and Running

Build by making a build directory (i.e. build/), run cmake in that dir, and then use make to build the desired target.

Example:

> mkdir build && cd build
> cmake .. -DCMAKE_BUILD_TYPE=[Debug | Coverage | Release]
> make

For testing, first start the main executable and then run the python test script in another console

> ./main         # Runs the main executable
> python3 ../tests/python-testclient/pythonTcpClient.py #runs a sample python client 

For unit testing folow this instructions

> make test      # Makes and runs the tests.
> make coverage  # Makes and runs the tests, then Generates a coverage report. (requires "cmake .. -DCMAKE_BUILD_TYPE=Coverage")
> make doc       # Generate html documentation.
> ./unit_tests -s #runs unittests with details
> 

Testing

There are some simple tests implemented in C++ the most important test is a set of scripts

start the main app in a console and in another console type one of the following
/tests/python-testclient$ python pythonTcpClient.py -ip 127.0.0.1 /tests/python-testclient$ python pythonTcpClient.py -ip 127.0.0.1 -f ../samplestate.txt /tests/python-testclient$ ./runclientlocal.sh

epollcoroutinedoctest's People

Contributors

g10h4ck avatar javierajorge avatar javierbrk avatar

Watchers

 avatar  avatar  avatar

Forkers

libremesh

epollcoroutinedoctest's Issues

Epoll notifica sobre un evento que ya no es de nuestro interes

Muchas veces sucede una race condition en la que un evento se dispara y luego se cierra el fd y se dessuscribe al fd de epool pero epool ya tiene registro del evento y nos intenta notificar. Esa notificación dispara una invocación de una a un resume (rec/send) y ya no existe corrutina que invocar. Eso se resolvia verificando la corrutina if (!coroRecv_) o con el contadro de los asinc file descritpor if (number > 51 ) pero no es elegante y puede fallar.

Este evento se podía observar puntualmente cuando se espera a que un proceso muera. Se realiza la llamada a sistema, la misma no se suspende pues responde rápido, pero el fd esta suscripto a epoll, cuando se termina de procesar la llamada el fd se elimina y se cierra. pero epoll nos envia una última notificacón en el próximo run. Tambíen se podría realizar la suscripción solo despues de que la llamada se suspende pero eso podría dar lugar a otra race condition en la que la notificacion llegue al kernel antes de lograr la suscripción. mas info en illumos.org/man/7/epoll
Para resolver esto se implementó una lista de filedescriptors que nos interesa manejar con epoll y que cuando ya no nos intersa simplemente lo quitamos de esa lista y con ello evitamos invocar un resume que ya no existe.

D 1688042710.168 void IOContext::detach(AsyncFileDescriptor*) detaching 25
D 1688042710.168 std::task::~task() [with T = bool] #941
D 1688042710.168 std::task::~task() [with T = bool] have you finished ? 1, task disposable = 0
D 1688042710.168 std::task::~task() [with T = bool] I'll destroy m_coro
D 1688042710.168 std::detail::promise_type_base::~promise_type_base() [with T = bool] 941 -- Promise: dtor
D 1688042710.168 std::task::~task() [with T = bool] i've just destroyed m_coro
D 1688042710.168 std::task client_socket_handler(std::unique_ptr) END
D 1688042710.168 Socket::~Socket() ------delete the socket(15)

D 1688042710.168 AsyncFileDescriptor::~AsyncFileDescriptor() ------delete the AsyncFileDescriptor(15)
number 27
D 1688042710.168 void IOContext::detach(AsyncFileDescriptor*) detaching 15
D 1688042710.168 std::detail::promise_type_base::~promise_type_base() [with T = bool] 940 -- Promise: dtor
D 1688042710.168 void IOContext::run() llamando en in al ptr 93824992902992 fd 1867742778
D 1688042710.168 bool AsyncFileDescriptor::resumeRecv() number 757935405

SocketSendOperation; ReturnValue = long int] error: 14 Bad address category: generic A syscall has failed

Agregar handler de este error

D 1687961039.260 FileReadOperation::~FileReadOperation() ~FileReadOperation
D 1687961039.260 std::task echo_loop(Socket&) readpipe aaaaaaaaaaaaaaaa () ammount-1
D 1687961039.260 std::task echo_loop(Socket&) SENDING ():
D 1687961039.260 BlockSyscall<SyscallOpt, ReturnValue>::BlockSyscall(std::shared_ptrstd::error_condition) [with SyscallOpt = SocketSendOperation; ReturnValue = long int] haveSuspend_
D 1687961039.260 SocketSendOperation::SocketSendOperation(Socket*, const uint8_t*, std::size_t, std::shared_ptrstd::error_condition) socket_send_operation

D 1687961039.260 bool BlockSyscall<SyscallOpt, ReturnValue>::await_ready() const [with SyscallOpt = SocketSendOperation; ReturnValue = long int] await_ready
D 1687961039.260 bool BlockSyscall<SyscallOpt, ReturnValue>::await_suspend(std::__n4861::coroutine_handle) [with SyscallOpt = SocketSendOperation; ReturnValue = long int] await_suspend
D 1687961039.260 ssize_t SocketSendOperation::syscall() send(6 content ammount 18446744073709551615)
D 1687961039.260 ReturnValue BlockSyscall<SyscallOpt, ReturnValue>::await_resume() [with SyscallOpt = SocketSendOperation; ReturnValue = long int] await_resume
D 1687961039.260 SocketSendOperation::~SocketSendOperation() ~socket_send_operation

D 1687961039.260 std::task echo_loop(Socket&) SENDING ():
D 1687961039.260 BlockSyscall<SyscallOpt, ReturnValue>::BlockSyscall(std::shared_ptrstd::error_condition) [with SyscallOpt = SocketSendOperation; ReturnValue = long int] haveSuspend_
D 1687961039.261 SocketSendOperation::SocketSendOperation(Socket*, const uint8_t*, std::size_t, std::shared_ptrstd::error_condition) socket_send_operation

D 1687961039.261 bool BlockSyscall<SyscallOpt, ReturnValue>::await_ready() const [with SyscallOpt = SocketSendOperation; ReturnValue = long int] await_ready
D 1687961039.261 bool BlockSyscall<SyscallOpt, ReturnValue>::await_suspend(std::__n4861::coroutine_handle) [with SyscallOpt = SocketSendOperation; ReturnValue = long int] await_suspend
D 1687961039.261 ssize_t SocketSendOperation::syscall() send(6 content ammount 18446744073709420543)
F 1687961039.261 bool BlockSyscall<SyscallOpt, ReturnValue>::await_suspend(std::__n4861::coroutine_handle) [with SyscallOpt = SocketSendOperation; ReturnValue = long int] error: 14 Bad address category: generic A syscall has failed

shared state not working as an invoked command

Test with ls -la and cat works as expected. But when trying to execute shared state specific command the output is only the command name.
First compile the binary and run it in the router, then cat the contents of the samplestate.txt file and send it to the router using a pipe connected netcat.

cat samplestate.txt | nc 10.13.40.149 3490
ls
drwxr-xr-x 1 root root 0 Jan 7 03:18 .
drwxr-xr-x 1 root root 0 Jan 3 01:14 ..
-rw-r--r-- 1 root root 391 Jan 3 02:12 nodedata.txt
-rw-r--r-- 1 root root 390 Jan 3 02:11 shared-state-sample.txt

$ cat samplestate.txt | nc 10.13.40.149 3490
shared-state

diff of the debugging messages can be found here https://editor.mergely.com/aCvc2vVA

Connection reset by peer

ests/python-testclient/pythonTcpClient.py", line 88, in
data = s.recv(1024)
ConnectionResetError: [Errno 104] Connection reset by peer

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.