I’m working on an Android NDK project where I need to bind a Unix domain socket to a path in the app’s internal storage. However, the bind() call occasionally fails with ENOENT (No such file or directory) on some devices. Most devices run the code without any issues, but on those where the error occurs, it happens consistently and never succeeds.
Here are the details:
Path used: /data/user/0/xxx.xxx.xxx.xxx/files/socket
Error message: bind() failed with errno: 2, [No such file or directory]
The code snippet for binding the socket is as follows:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <cstdio>
#include <string>
bool create_and_listen(const std::string& name) {
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
std::string path = "/data/user/0/xxx.xxx.xxx.xxx/files/"(this path is got from context.GetFilesDir() from Android Activity) + name;
strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path) - 1);
int listen_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (listen_socket == -1) {
perror("Failed to create socket");
return false;
}
unlink(addr.sun_path); // Remove old socket file if it exists
if (bind(listen_socket, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("bind error");
printf("Failed to bind socket, path: %s, errno: %dn", path.c_str(), errno);
return false;
}
if (listen(listen_socket, SOMAXCONN) == -1) {
perror("listen error");
printf("Failed to listen on socket, path: %s, errno: %dn", path.c_str(), errno);
return false;
}
printf("Successfully listening on Unix domain socket: %sn", path.c_str());
return true;
}
int main() {
create_and_listen("socket");
return 0;
}
What I’ve checked so far:
- Path existence: The directory
/data/user/0/com.levelinfinite.sgameGlobal/files/ exists, and I can
create regular files in it without any issues. - Path length: The full path length is well within the 108-byte limit
for Unix domain socket paths. - Permissions: Since this is the app’s internal storage, the app has
full read/write permissions.
Additional Clues:
- Once a device exhibits this issue, it consistently fails and never
succeeds in binding. - The path is definitely valid, as I can
successfully create other regular files in the same directory.
Questions:
Why would bind() return ENOENT when the path clearly exists and is writable?
Are there any specific considerations or restrictions on Unix domain sockets in Android’s internal storage that I might be missing?
Any insights or suggestions would be greatly appreciated!