{"id":19892614,"url":"https://github.com/compscidr/non-blocking-sockets","last_synced_at":"2026-06-09T03:03:57.178Z","repository":{"id":89825183,"uuid":"371478426","full_name":"compscidr/non-blocking-sockets","owner":"compscidr","description":"Non blocking tcp and modbus sockets","archived":false,"fork":false,"pushed_at":"2023-12-05T17:48:59.000Z","size":18,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-22T01:35:13.515Z","etag":null,"topics":["cpp","libmodbus","modbus","sockets","tcp"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/compscidr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-27T19:09:57.000Z","updated_at":"2023-12-05T17:48:54.000Z","dependencies_parsed_at":"2023-12-05T18:46:03.435Z","dependency_job_id":"96f38838-d77d-4eb1-b04f-8670bd64c21a","html_url":"https://github.com/compscidr/non-blocking-sockets","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compscidr%2Fnon-blocking-sockets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compscidr%2Fnon-blocking-sockets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compscidr%2Fnon-blocking-sockets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compscidr%2Fnon-blocking-sockets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/compscidr","download_url":"https://codeload.github.com/compscidr/non-blocking-sockets/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241320966,"owners_count":19943826,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","libmodbus","modbus","sockets","tcp"],"created_at":"2024-11-12T18:24:27.193Z","updated_at":"2026-06-09T03:03:52.140Z","avatar_url":"https://github.com/compscidr.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Non-blocking shutdown of tcp and modbus sockets in c/c++\nThis PoC project was motivated by some work we were doing with the libmodbus-dev library. \n\nWe were creating a server which was doing listen / accept in a thread, and wanting to cleanly shut it down. Once the `accept` call is reached, from what I can\ntell, it's impossible to get it to unblock until an actual connection is made. \n\nThis differs from java, and other high level languages in that, typically you can simply close the socket and it will release the block. This is not the case\nwith c++/c sockets.\n\nAt first, I though it might be just a libmodbus problem, but I built another PoC using just simple tcp sockets and found it was the same.\n\nThis PoC shows how it can be cleanly shutdown using both tcp and modbus sockets.\n\n## self pipe, select approach\nThere are a few approaches which could be taken, however this one uses low cpu (doesn't poll, doesn't require timeouts).\n\nThe approach I'm using is to ~~set the sockets into non-blocking mode and~~ (not necessary, and didn't work with libmodbus) use `SELECT` to monitor groups of file descriptors which are ready to read (accept) and write. \n\nA self-pipe is used, and added to the read descriptors. A signal handler is registered to the `SIGUSR1` signal. When this signal is received, it\nwrites to the self-pipe. This triggers the `SELECT` since it is waiting on a read from the pipe + the server socket. It then breaks out of its\nlistening loop and cleanly closes.\n\nA `stop` call can used to raise the SIGUSR1 signal to kick this off from another thread.\n\n## Three programs\n1. tcp_blocking_server: This demonstrates the problem using a tcp server\n2. tcp_server: A PoC showing the fix\n3. modbus_server: A libmodbus PoC with the fix\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcompscidr%2Fnon-blocking-sockets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcompscidr%2Fnon-blocking-sockets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcompscidr%2Fnon-blocking-sockets/lists"}