CURLOPT_CLOSESOCKETFUNCTION(3)
π CURLOPT_CLOSESOCKETFUNCTION β bestie, it's the socket-close replacement callback
Okay so real talk, this page lives in the libcurl manual (that's the manual name, bestie, we're in the library functions section, mwah) β¨ and it's all about CURLOPT_CLOSESOCKETFUNCTION, aka the callback to socket close replacement. Iconic behaviour. Let's get into it π
β¨ SYNOPSIS β¨
#include <curl/curl.h>
int closesocket_callback(void *clientp, curl_socket_t item);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CLOSESOCKETFUNCTION,
closesocket_callback);
π¦ DESCRIPTION π¦
So you pass in a pointer to your callback function, and it has to match the prototype up there β¬οΈ β like, exactly, no freestyling.
Here's the vibe: libcurl calls your function instead of the close(3) or closesocket(3) call whenever sockets get closed. And heads up β that's sockets only, not any other file descriptors, okay? It's pretty much the reverse twin of CURLOPT_OPENSOCKETFUNCTION(3). Return 0 to signal success, and return 1 if there was an error. That's the whole contract π
The clientp pointer? That's set with CURLOPT_CLOSESOCKETDATA(3). And item is the socket that libcurl wants to be closed. Simple as that.
π«Ά Okay this part matters, don't scroll past: when you're using multi/share handles, your callback may get invoked even after the easy handle has been cleaned up. The callback and data get inherited by a new connection, and that connection may live longer than the transfer itself in the multi/share handle's connection cache. So like... don't be shocked, it's documented behaviour, not a haunting π»
πΈ DEFAULT πΈ
It just uses the standard socket close function. Classic. No notes.
π PROTOCOLS π
This functionality affects all supported protocols. All of them. Every single one. we love an inclusive queen π
β EXAMPLE β
struct priv {
void *custom;
};
static int closesocket(void *clientp, curl_socket_t item)
{
struct priv *my = clientp;
printf("our ptr: %p\n", my->custom);
printf("libcurl wants to close %d now\n", (int)item);
return 0;
}
int main(void)
{
struct priv myown;
CURL *curl = curl_easy_init();
/* call this function to close sockets */
curl_easy_setopt(curl, CURLOPT_CLOSESOCKETFUNCTION, closesocket);
curl_easy_setopt(curl, CURLOPT_CLOSESOCKETDATA, &myown);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
See how closesocket gets wired up with CURLOPT_CLOSESOCKETFUNCTION and the data goes in through CURLOPT_CLOSESOCKETDATA? Chef's kiss. It ate π₯
π§ AVAILABILITY π§
Added in curl 7.21.7. So she's been around a minute π
π RETURN VALUE π
curl_easy_setopt(3) returns a CURLcode indicating success or error.
CURLE_OK (0) means everything was OK β slay. Non-zero means an error occurred, so go check libcurl-errors(3) for the tea.
π SEE ALSO π
That's the whole page, bestie, no crumbs left π This was libcurl, dated 2026-10-12, brought to you by the CURLOPT_CL...KETFUNCTION(3) girlies β go close some sockets responsibly, ily, bye! πβ¨π
π¦ where this page comes from
- fedora 44: libcurl-devel 8.18.0-14.fc44 Β· curl
- fedora 44: libcurl-devel 8.18.0-14.fc44 Β· curl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms