* bug fix: more cleanups to the floating point exception handling on
x86-64 (thanks to James Knight)
* contrib improvement: it's harder to cause SOCKET-CLOSE to close()
- the wrong file descriptor. (thanks to Tony Martinez)
+ the wrong file descriptor; implementation of SOCKET-OPEN-P.
+ (thanks to Tony Martinez)
* fixed some bugs revealed by Paul Dietz' test suite:
** Invalid dotted lists no longer raise a read error when
*READ-SUPPRESS* is T
socket-send socket-receive socket-recv
socket-name socket-peername socket-listen
socket-close socket-file-descriptor
- socket-family socket-protocol socket-type
- socket-make-stream get-protocol-by-name
+ socket-family socket-protocol socket-open-p
+ socket-type socket-make-stream get-protocol-by-name
get-host-by-name get-host-by-address
host-ent
(if (= r -1)
(socket-error "listen"))))
+(defgeneric socket-open-p (socket)
+ (:documentation "Return true if SOCKET is open; otherwise, return false.")
+ (:method ((socket t)) (error 'type-error
+ :datum socket :expected-type 'socket)))
+
+(defmethod socket-open-p ((socket socket))
+ (if (slot-boundp socket 'stream)
+ (open-stream-p (slot-value socket 'stream))
+ (/= -1 (socket-file-descriptor socket))))
+
(defgeneric socket-close (socket)
- (:documentation "Close SOCKET. May throw any kind of error that write(2) would have
-thrown. If SOCKET-MAKE-STREAM has been called, calls CLOSE on that
-stream instead"))
+ (:documentation "Close SOCKET. May throw any kind of error that
+write(2) would have thrown. If SOCKET-MAKE-STREAM has been called,
+calls CLOSE on that stream instead"))
(defmethod socket-close ((socket socket))
;; the close(2) manual page has all kinds of warning about not
(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))
+ (unwind-protect (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
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
+(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
SB-SYS:MAKE-FD-STREAM."))
-(defmethod socket-make-stream ((socket socket) &rest args)
+(defmethod socket-make-stream ((socket socket) &rest args)
(let ((stream
(and (slot-boundp socket 'stream) (slot-value socket 'stream))))
(unless stream
(network-unreachable-error () 'network-unreachable))
t)
+(deftest socket-open-p-true.1
+ (socket-open-p (make-instance 'inet-socket :type :stream :protocol :tcp))
+ t)
+#+internet-available
+(deftest socket-open-p-true.2
+ (let ((s (make-instance 'inet-socket :type :stream :protocol :tcp)))
+ (unwind-protect
+ (progn
+ (socket-connect s #(127 0 0 1) 7)
+ (socket-open-p s))
+ (socket-close s)))
+ t)
+(deftest socket-open-p-false
+ (let ((s (make-instance 'inet-socket :type :stream :protocol :tcp)))
+ (socket-close s)
+ (socket-open-p s))
+ nil)
;;; we don't have an automatic test for some of this yet. There's no
;;; simple way to run servers and have something automatically connect