Since the client code for the database is probably not written in such a way that it can deal with cancellation (most library code is not), I don't think this approach will work. For more details see section Zak.
If you need to cancel connections to the database, you probably have to proxy the connection and kill the proxy. Basically, you should create a second thread that listens on the port and redirects the connection to the database server, and direct the database client to connect to this port on the local host instead of the real database server / port. The proxy stream can then be canceled (with normal delayed cancellation rather than asynchronous), with a cancellation clearing handler to disable sockets. Losing the connection to the database server through a private socket (and not just a non-sensitive socket) should result in an error returning the database client library code, and you can also close the stream.
Keep in mind that when setting up such a proxy server, you need to make sure that you are not introducing security problems with access to the database.
Here is a sketch of the code that you could use for a proxy, without error checking logic and without any explanation for unexpected clients connecting:
int s, c; struct addrinfo *ai; struct sockaddr_in sa; char portstr[8]; getaddrinfo(0, 0, &(struct addrinfo){ .ai_flags = AI_PASSIVE, .ai_family = AF_INET }, &ai); s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); bind(s, ai->ai_addr, ai_addrlen); freeaddrinfo(ai); getsockname(s, (void *)&sa, &(socklen_t){sizeof sa}); port = ntohs(sa.sin_port); listen(s, 1); c = accept(s, &sa, &(socklen_t){sizeof sa}); close(s); getaddrinfo("dbserver", "dbport", 0, &ai); s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); connect(s, ai->ai_addr, ai->ai_addrlen); freeaddrinfo(ai);
At this point, you have two sockets, s connected to the database server, and c connected to the database client in another thread in your program. Everything that you read from one must be written to another; use poll to determine which one is ready to be read or written.
During the above installation code, the cancellation should be blocked, except for accept and connect calls, and at these points you need the appropriate cleanup handlers to close your sockets and call freeaddrinfo if the cancellation occurs. It might make sense to copy the data you use from getaddrinfo into local variables so that you can freeaddrinfo before blocking calls and not worry about doing this from the undo clearing handler.