Windows: Can't terminate-thread that's in the middle of a socket call

Bug #1453361 reported by No Name
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
New
Undecided
Unassigned

Bug Description

Here's some code that creates an immortal thread in Windows:

(defpackage immortal-thread
  (:use :common-lisp :sb-thread :sb-bsd-sockets))

(in-package :immortal-thread)

(make-thread
 (lambda ()
   (let* ((listen (make-instance 'sb-bsd-sockets:inet-socket
                              :type :stream :protocol :tcp))
   (accept nil)
   (connect (make-instance 'sb-bsd-sockets:inet-socket
      :type :stream :protocol :tcp)))
     (socket-bind listen #(127 0 0 1) 12121)
     (socket-listen listen 5)
     (setf accept (socket-accept listen)))))

The thread ends up as the CAR of (list-all-threads), so this should terminate it:

   (terminate-thread (car (list-all-threads)))

Doing (list-all-threads) after that shows that the thread is still there.

Also, (thread-alive-p (car (list-all-threads))) remains T.

The thread is not immortal on Linux. This is a Windows-specific problem.

I've also confirmed that this does not happen if the thread is in a busy-wait loop such as
(loop do (progn nil)).

*FEATURES* contains:

(CHIPZ-SYSTEM:GRAY-STREAMS :RUNE-IS-CHARACTER :CLOSER-MOP :FLEXI-STREAMS
 CFFI-FEATURES:FLAT-NAMESPACE CFFI-FEATURES:X86 CFFI-FEATURES:WINDOWS :CFFI
 CFFI-SYS::FLAT-NAMESPACE :WINDOWS :QUICKLISP :ASDF-PACKAGE-SYSTEM :ASDF3.1
 :ASDF3 :ASDF2 :ASDF :OS-WINDOWS :NON-BASE-CHARS-EXIST-P :ASDF-UNICODE :SWANK
 :ALIEN-CALLBACKS :ANSI-CL :ASH-RIGHT-VOPS :C-STACK-IS-CONTROL-STACK
 :COMMON-LISP :COMPARE-AND-SWAP-VOPS :CYCLE-COUNTER :GENCGC
 :IEEE-FLOATING-POINT :INLINE-CONSTANTS :LINKAGE-TABLE :LITTLE-ENDIAN
 :MEMORY-BARRIER-VOPS :MULTIPLY-HIGH-VOPS :OS-PROVIDES-DLOPEN
 :OS-PROVIDES-DLOPEN :OS-PROVIDES-PUTWC :PACKAGE-LOCAL-NICKNAMES
 :RAW-INSTANCE-INIT-VOPS :SB-DYNAMIC-CORE :SB-EVAL :SB-FUTEX :SB-LDB
 :SB-PACKAGE-LOCKS :SB-QSHOW :SB-SAFEPOINT :SB-SAFEPOINT-STRICTLY
 :SB-SOURCE-LOCATIONS :SB-TEST :SB-THREAD :SB-THRUPTION :SB-UNICODE :SB-WTIMER
 :SBCL :STACK-ALLOCATABLE-CLOSURES :STACK-ALLOCATABLE-FIXED-OBJECTS
 :STACK-ALLOCATABLE-LISTS :STACK-ALLOCATABLE-VECTORS
 :STACK-GROWS-DOWNWARD-NOT-UPWARD :SYMBOL-INFO-VOPS
 :UNWIND-TO-FRAME-AND-CALL-VOP :WIN32 :X86)

Revision history for this message
No Name (vvkdarrh) wrote :

More info: If you make a socket call from SLIME and it doesn't complete, you can't break out of it with C-c C-c like you'd normally be able to. SBCL cannot receive the interrupt from EMACS until the socket call completes.

Revision history for this message
No Name (vvkdarrh) wrote :

The problem seems like it may be related to this Stack Overflow question:

  http://stackoverflow.com/questions/28957279/how-to-exit-a-blocking-recv-call

However, the suggestion given there doesn't work. I tried sb-bsd-sockets:socket-shutdown, which gave the error "NIL fell through ECASE expression".

I also tried importing the "shutdown" function directly from Winsock (ws2_32.dll) and calling it with (socket-file-descriptor sock). It returned -1. The thread remains immortal.

Revision history for this message
No Name (vvkdarrh) wrote :

Calling (socket-close) on the relevant socket will cause the blocking call to unblock. However, this means that to kill a thread on Windows that may make blocking socket calls, the killer thread must have access to all the socket-calling thread's sockets so it can close them. This forces you to redesign your program if it was originally written on Linux, so it's still a bug.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.