我有套接字系列PF_PACKETtypesSOCK_RAW。 通过recvmsg和poll()读取消息。 无情地和周期性地我recvmsg返回EDEADLK。 我尝试用下面的代码来debugging这个问题。 我尝试调查谁和如何封锁我的套接字描述符。 可能有人知道其他的方法如何debugging这种情况? 正如我所理解的
避免EDEADLK资源死锁。 试图locking会导致死锁情况的系统资源。 在我的情况下,它是套接字文件描述符locking问题。 分配系统资源套接字文件描述符将导致死锁情况。 系统不保证它会注意到所有这些情况。 这个错误意味着你很幸运并且系统被注意到了。
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. }
如果recvmsg()
返回0,这并不意味着发生了错误。 这意味着另一端关闭了连接。
在对问题的后续评论中,OP提到他们使用if ((error = recvmsg()) <= 0) {return -errno;}
。 这是错误的。 当另一端关闭连接时, recvmsg()
返回零,不设置errno
。 即使使用名为error
的变量也是错误的,因为函数返回接收到的字节数。
换句话说,OP从其他一些早期失败的锁定函数中看到一个旧的,过时的errno == EDEADLK
,并且处理另一端错误地关闭连接的情况。
(错误发生时只设置errno
;没有任何库函数将其清零,因为在某些情况下可能会导致错误隐藏。