Reputation: 613
I have socket family PF_PACKET type SOCK_RAW. Messages read via recvmsg and with poll(). Rendomly and periodicly I got recvmsg return EDEADLK. I try debug this problem with next code. I try investigate who and how blocked my socket descriptor. May be some one know other method how debug such case? As I right understand
EDEADLK resource deadlock avoided. An attempt was made to lock a system resource that would have resulted in a deadlock situation. In my case it is socket file descriptor locking problem. Allocating a system resource socket file descriptor would have resulted in a deadlock situation. The system does not guarantee that it will notice all such situations. This error means you got lucky and the system noticed.
error = recvmsg(fd, &msghdr, flags);
msghdr_flags = msg_hdr.msg_flags;
void recvmsg_errno(int fd, unsigned int msghdr_flags, int flags, int error)
{
struct flock fl;
memset(&fl, 0x0, sizeof(fl));
printf("recvmsg return: %d errno: %d description: %s\n", error, errno,
strerror(errno));
printf("recvmsg flags: %x %d\n", flags, flags);
if (flags & MSG_ERRQUEUE) printf("MSG_ERRQUEUE\n");
if (flags & MSG_OOB) printf("MSG_OOB\n");
if (flags & MSG_PEEK) printf("MSG_PEEK\n");
if (flags & MSG_TRUNC) printf("MSG_TRUNC\n");
if (flags & MSG_WAITALL) printf("MSG_WAITALL\n");
printf("msghdr flags: %x %d\n", msghdr_flags, msghdr_flags);
if (msghdr_flags & MSG_EOR) printf("MSG_EOR\n"); //indicates end-of-record; SOCK_SEQPACKET
if (msghdr_flags & MSG_TRUNC) printf("MSG_TRUNC\n"); //discarded datagram was larger than the buffer supplied
if (msghdr_flags & MSG_CTRUNC) printf("MSG_CTRUNC\n"); //control data were discarded due to lack of space in the buffer
if (msghdr_flags & MSG_OOB) printf("MSG_OOB\n"); //out-of-band data were received
if (msghdr_flags & MSG_ERRQUEUE) printf("MSG_ERRQUEUE\n"); //no data received; extended error from the socket error queue
flags = 0;
flags = fcntl(fd, F_GETLK, &fl); {
printf("F_GETLK: 0x%x\n", flags);
printf("l_start: %x l_len: %x l_pid: %d l_type: %x l_whence: %x\n",
fl.l_start, //Starting offset for lock
fl.l_len, //Number of bytes to lock
fl.l_pid, //PID of process blocking our lock (F_GETLK only)
fl.l_type, //Type of lock: F_RDLCK, F_WRLCK, F_UNLCK
fl.l_whence); // How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END
}//Get the first lock which blocks the lock description
flags = 0;
flags = fcntl(fd, F_GETFD); {
printf("F_GETFD: 0x%x\n", flags);
}//Get the file descriptor flags
flags = 0;
flags = fcntl(fd, F_GETFL); {
printf("F_GETFL: 0x%x\n", flags);
if (flags & O_NONBLOCK) printf("O_NONBLOCK\n");
if (!(flags & O_NONBLOCK)) printf("BLOCK\n");
if (flags & O_APPEND) printf("O_APPEND\n");
}//Get the file status flags and file access modes
flags = 0;
flags = fcntl(fd, F_GETOWN); {
printf("F_GETOWN: %d\n", flags);
}//Socket, set the process or process group ID specified to receive SIGURG signals when out-of-band data is available.
}
Upvotes: 3
Views: 1867
Reputation: 39406
If recvmsg()
returns 0, it does not mean an error occurred. It means that the other end closed the connection.
In a followup comment to the question, the OP mentioned that they used if ((error = recvmsg()) <= 0) {return -errno;}
. This is wrong. When the other end closes the connection, recvmsg()
returns zero, without setting errno
. Even the use of variable named error
is wrong, as the function returns the number of bytes received.
In other words, the OP is seeing an old, stale errno == EDEADLK
from some other earlier failed locking function, and handling the case where the other end closes the connection incorrectly as an error.
(errno
is only set when an error occurs; no library function clears it to zero, ever, because that could cause errors to be hidden in certain cases.)
Upvotes: 8