- &key
- oob peek waitall
- (element-type 'character))
- (let ((flags
- (logior (if oob sockint::MSG-OOB 0)
- (if peek sockint::MSG-PEEK 0)
- (if waitall sockint::MSG-WAITALL 0)
- sockint::MSG-NOSIGNAL ;don't send us SIGPIPE
- (if (eql (socket-type socket) :datagram)
- sockint::msg-TRUNC 0)))
- (sockaddr (make-sockaddr-for socket)))
- (unless (or buffer length)
- (error "Must supply at least one of BUFFER or LENGTH"))
- (unless buffer
- (setf buffer (make-array length :element-type element-type)))
- (sb-alien:with-alien ((sa-len (array (sb-alien:unsigned 32) 2)))
- (setf (sb-alien:deref sa-len 0) (size-of-sockaddr socket))
- (sb-sys:with-pinned-objects (buffer sockaddr)
- (let ((len
- (sockint::recvfrom (socket-file-descriptor socket)
- (sb-grovel::array-data-address buffer)
- (or length (length buffer))
- flags
- (sb-grovel::array-data-address sockaddr)
- (sb-alien:cast sa-len (* integer)))))
- (when (= len -1) (socket-error "recvfrom"))
- (apply #'values buffer len (multiple-value-list
- (bits-of-sockaddr socket sockaddr))))))))
+ &key
+ oob peek waitall
+ (element-type 'character))
+ (with-sockaddr-for (socket sockaddr)
+ (let ((flags
+ (logior (if oob sockint::MSG-OOB 0)
+ (if peek sockint::MSG-PEEK 0)
+ (if waitall sockint::MSG-WAITALL 0)
+ #+linux sockint::MSG-NOSIGNAL ;don't send us SIGPIPE
+ (if (eql (socket-type socket) :datagram)
+ sockint::msg-TRUNC 0))))
+ (unless (or buffer length)
+ (error "Must supply at least one of BUFFER or LENGTH"))
+ (unless length
+ (setf length (length buffer)))
+ (let ((copy-buffer (sb-alien:make-alien (array sb-alien:unsigned 1) length)))
+ (unwind-protect
+ (sb-alien:with-alien ((sa-len (array (sb-alien:unsigned 32) 2)))
+ (setf (sb-alien:deref sa-len 0) (size-of-sockaddr socket))
+ (let ((len
+ (sockint::recvfrom (socket-file-descriptor socket)
+ copy-buffer
+ length
+ flags
+ sockaddr
+ (sb-alien:cast sa-len (* integer)))))
+ (cond
+ ((and (= len -1) (= sockint::EAGAIN (sb-unix::get-errno))) nil)
+ ((= len -1) (socket-error "recvfrom"))
+ (t (loop for i from 0 below len
+ do (setf (elt buffer i) (sb-alien:deref copy-buffer i)))
+ (apply #'values buffer len (multiple-value-list
+ (bits-of-sockaddr socket sockaddr)))))))
+ (sb-alien:free-alien copy-buffer))))))