<div dir="ltr">Hi Chun,<div><br></div><div>Thanks for looking into this. I've just pulled the most recent codes from github and have had a little play with them. I now get an error signalled on the socket-receive when I expect an error (rather than a simple -1 count as before). This is good.</div><div><br></div><div>However, I am still seeing the socket-state behaviour I described before, along with a new bug that has probably been introduced by the recent changes.</div><div><br></div><div>Consider the following simple function which listens for UDP port 8001 for up to 4 iterations:</div><div><div><br></div><div><div>(defun usocket-test ()</div><div> (let ((s (usocket:socket-connect nil nil </div><div><span class="" style="white-space:pre">                    </span>   :protocol :datagram</div><div><span class="" style="white-space:pre">                            </span>  :element-type '(unsigned-byte 8)</div><div><span class="" style="white-space:pre">                            </span>  :local-port 8001)))</div><div>   (unwind-protect </div><div>       (do ((i 0 (1+ i))</div><div>            (buffer (make-array 1024 :element-type '(unsigned-byte 8) :initial-element 0))</div><div>            (done nil))</div><div>           ((or done (= i 4))</div><div>            nil)</div><div>         (when (usocket:wait-for-input s :ready-only t :timeout 10)</div><div>           (format t "~D state ~S~%" i (usocket::state s))</div><div>           (handler-case </div><div>               (multiple-value-bind (buffer count remote-host remote-port)               </div><div>                   (usocket:socket-receive s buffer 1024)</div><div>                 (handler-case </div><div>                     (usocket:socket-send s (subseq buffer 0 count)</div><div>                                          :host remote-host</div><div>                                          :port remote-port)</div><div>                   (error (c)</div><div>                     (format t "socket-send error: ~A~%" c))))</div><div>             (error (c)</div><div>               (format t "socket-receive error: ~A~%" c)))))</div><div>     (usocket:socket-close s))))</div><div><br></div></div></div><div><br></div><div>after calling this from your repl, from another process send a UDP packet to port 8001 to get things going. I get the following output:</div><div><br></div><div><div><div>0 state :READ</div><div>socket-send error: #<STANDARD-GENERIC-FUNCTION USOCKET:SOCKET-SEND 21CADCFA> is called with unpaired keyword in (2130706433 :PORT 58279).</div><div>1 state :READ</div><div>socket-receive error: MAKE-INSTANCE is called with keyword :SOCKET among the arguments (USOCKET:NS-TRY-AGAIN-CONDITION :SOCKET 2604) which is not one of (:HOST-OR-IP).</div><div>2 state :READ</div><div>socket-receive error: MAKE-INSTANCE is called with keyword :SOCKET among the arguments (USOCKET:NS-TRY-AGAIN-CONDITION :SOCKET 2604) which is not one of (:HOST-OR-IP).</div><div>3 state :READ</div><div>socket-receive error: MAKE-INSTANCE is called with keyword :SOCKET among the arguments (USOCKET:NS-TRY-AGAIN-CONDITION :SOCKET 2604) which is not one of (:HOST-OR-IP).</div><div>NIL</div></div></div><div><br></div><div>My observations:</div><div>1. The initial socket-receive succeeds (as expected).</div><div>2. The initial socket-send fails with an error I've not seen before and can't diagnose... </div><div>3. Subsequent calls to wait-for-input return immediately because the socket is still in a :READ state, even though I already successfully called socket-receive in the first iteration.</div><div>4. Subsequent calls to socket-receive now fail with a different error I can't diagnose.</div><div><br></div><div>If I didn't have the max iteration cap, this would spin using 100% of a CPU core and adding around 2MB to the heap per second (on my machine), maxing out the 1GB personal edition heap limit in a short space of time. So I think it's a pretty serious issue. I mainly use SBCL, I use LispWorks occasionally to make sure my codes work on at least 1 other implementation, so I'm not exactly a LispWorks expert.</div><div><br></div><div>If you want any more explanations, clarifications or examples I'll be happy to do my best to help. </div><div><br></div><div>As before, I'm using LispWorks personal edition 6.1.1 on Windows 8.1. </div><div><br></div><div>Frank.</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On 22 May 2015 at 09:24, Chun Tian (binghe) <span dir="ltr"><<a href="mailto:binghe.lisp@gmail.com" target="_blank">binghe.lisp@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Frank,<br>
<br>
Today I have modified SOCKET-SEND and SOCKET-RECEIVE for LispWorks, to be able to detect and report socket errors.  I think in this way, these APIs on LispWorks could behavior closer to other platforms.<br>
<br>
Now on Windows, your test code should return a USOCKET:CONNECTION-RESET-ERROR condition, which equals to WSA error ECONNRESET.  However, when I test the same code on Mac OS X, it instead returns USOCKET:CONNECTION-REFUSED-ERROR, I think this is a behavior of BSD sockets.<br>
<br>
I hope you can try latest usocket code from Git [1], to see if it works better for your case now. My code changes commit can be seen here [2].<br>
<br>
For wait-for-input, I can’t see what you see (the socket object remains in a :READ state), if you still think this is an issue, I hope you can create another test code to demonstrate this issue.<br>
<br>
Regards,<br>
<br>
Chun<br>
<br>
[1] <a href="https://github.com/usocket/usocket" target="_blank">https://github.com/usocket/usocket</a><br>
[2] <a href="https://github.com/usocket/usocket/commit/13386639889fa812540fc4f77824c47e7616db37" target="_blank">https://github.com/usocket/usocket/commit/13386639889fa812540fc4f77824c47e7616db37</a><br>
<span class="im HOEnZb"><br>
Il giorno 10/apr/2015, alle ore 23:00, Frank James <<a href="mailto:frank.a.james@gmail.com">frank.a.james@gmail.com</a>> ha scritto:<br>
<br>
</span><div class="HOEnZb"><div class="h5">> I've been testing some UDP codes on Lispworks (personal 32bit Windows version) and have encountered some undocumented behaviour, I think it's a matter of opinion whether it's a bug or not but it should probably have a sentence or two documenting it somewhere.<br>
><br>
> Basically I'm sending a UDP packet to a host and listening for a reply, using socket-send and socket-receive. If the host in question is not listening for UDP traffic on that particular port, the Windows socket API says it should return an ECONNRESET error immediately on the socket-receive call, this is indicated by a -1 return value from the underlying recvfrom call.<br>
><br>
> When this happens the Lispworks backend code returns a length of -1 (and buffer nil). This is perfectly acceptable behaviour I think (although it'd be somewhat nicer to signal an error, but that's a matter of taste). But it should be documented that checking the length here is the correct way to detect an error occurred.<br>
><br>
> Example code would be something like:<br>
><br>
> (let ((sock (usocket:socket-connect "localhost" 1234 :protocol :datagram :element-type '(unsigned-byte 8))))<br>
>   (unwind-protect<br>
>     (progn<br>
>       (usocket:socket-send sock (make-array 16 :element-type '(unsigned-byte 8) :initial-element 0) 16)<br>
>       (let ((buffer (make-array 16 :element-type '(unsigned-byte 8) :initial-element 0)))<br>
>         (usocket:socket-receive sock buffer 16)))<br>
>     (usocket:socket-close sock)))<br>
><br>
><br>
> What is somewhat more annoying is that the socket object remains in a :READ state. This means that a polling loop using wait-for-input spins continuously, with each socket-receive returning -1 (as explained above). Probably the socket state should be cleared if a socket-receive fails.<br>
><br>
> Apologies if this is all well-known to those reading this list, but it caused me 10 minutes of head scratching earlier today and thought it was worth mentioning.<br>
><br>
> Frank.<br>
><br>
<br>
</div></div></blockquote></div><br></div>