(let ((sockaddr (apply #'make-sockaddr-for socket nil address)))
(if (= (sb-sys:with-pinned-objects (sockaddr)
(sockint::bind (socket-file-descriptor socket)
- (sockint::array-data-address sockaddr)
+ (sb-grovel::array-data-address sockaddr)
(size-of-sockaddr socket)))
-1)
(socket-error "bind"))))
(let ((sockaddr (make-sockaddr-for socket)))
(sb-sys:with-pinned-objects (sockaddr)
(let ((fd (sockint::accept (socket-file-descriptor socket)
- (sockint::array-data-address sockaddr)
+ (sb-grovel::array-data-address sockaddr)
(size-of-sockaddr socket))))
(apply #'values
(if (= fd -1)
(let* ((sockaddr (apply #'make-sockaddr-for socket nil peer)))
(if (= (sb-sys:with-pinned-objects (sockaddr)
(sockint::connect (socket-file-descriptor socket)
- (sockint::array-data-address sockaddr)
+ (sb-grovel::array-data-address sockaddr)
(size-of-sockaddr socket)))
-1)
(socket-error "connect") )))
(let* ((sockaddr (make-sockaddr-for socket)))
(when (= (sb-sys:with-pinned-objects (sockaddr)
(sockint::getpeername (socket-file-descriptor socket)
- (sockint::array-data-address sockaddr)
+ (sb-grovel::array-data-address sockaddr)
(size-of-sockaddr socket)))
-1)
(socket-error "getpeername"))
(let* ((sockaddr (make-sockaddr-for socket)))
(when (= (sb-sys:with-pinned-objects (sockaddr)
(sockint::getsockname (socket-file-descriptor socket)
- (sockint::array-data-address sockaddr)
+ (sb-grovel::array-data-address sockaddr)
(size-of-sockaddr socket)))
-1)
(socket-error "getsockname"))
(sb-sys:with-pinned-objects (buffer sockaddr)
(let ((len
(sockint::recvfrom (socket-file-descriptor socket)
- (sockint::array-data-address buffer)
+ (sb-grovel::array-data-address buffer)
(or length (length buffer))
flags
- (sockint::array-data-address sockaddr)
+ (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
;; descriptor). Presumably this is an oversight and we could also
;; get anything that write(2) would have given us.
- ;; What we do: we catch EBADF. It should only ever happen if
- ;; (a) someone's closed the socket already (stream closing seems
- ;; to have this effect) or (b) the caller is messing around with
- ;; socket internals. That's not supported, dude
-
- (if (slot-boundp socket 'stream)
- (close (slot-value socket 'stream)) ;; closes socket as well
- (handler-case
- (if (= (sockint::close (socket-file-descriptor socket)) -1)
- (socket-error "close"))
- (bad-file-descriptor-error (c) (declare (ignore c)) nil)
- (:no-error (c) (declare (ignore c)) nil))))
+ ;; note that if you have a socket _and_ a stream on the same fd,
+ ;; the socket will avoid doing anything to close the fd in case
+ ;; the stream has done it already - if so, it may have been
+ ;; reassigned to some other file, and closing it would be bad
+
+ (let ((fd (socket-file-descriptor socket)))
+ (cond ((eql fd -1) ; already closed
+ nil)
+ ((slot-boundp socket 'stream)
+ (close (slot-value socket 'stream)) ;; closes fd
+ (setf (slot-value socket 'file-descriptor) -1)
+ (slot-makunbound socket 'stream))
+ (t
+ (sb-ext:cancel-finalization socket)
+ (handler-case
+ (if (= (sockint::close fd) -1)
+ (socket-error "close"))
+ (bad-file-descriptor-error (c) (declare (ignore c)) nil)
+ (:no-error (c) (declare (ignore c)) nil))))))
+
(defgeneric socket-make-stream (socket &rest args)
(:documentation "Find or create a STREAM that can be used for IO
on SOCKET (which must be connected). ARGS are passed onto