rpav / ScriptL

Shell scripting made Lisp-like! Or, live-coding remote function calls for the shell.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error under LispWorks 7.1.2 when running cli command

svetlyak40wt opened this issue · comments

When running server under LispWorks 7.1.2 I get this error during command execution (I'm trying example from the README):

#(48 48 48 48 48 48 48 54) cannot be converted to foreign type "Statically allocated (LISP-ARRAY NIL)".
Call to ERROR
Call to FLI::FOREIGN-TYPE-ERROR-FUNCTION
Call to FLI::CHECKED-LISP-ARRAY
Call to FLI::SET-DYNAMIC-LISP-ARRAY-POINTER
Call to IOLIB/STREAMS::IOBUF-COPY-FROM-LISP-ARRAY
Call to IOLIB/STREAMS::IOBUF-APPEND-SLICE
Call to IOLIB/STREAMS::%WRITE-SIMPLE-ARRAY-UB8
Call to WRITE-SEQUENCE
Call to SCRIPTL::SEND-PACKET
Call to (HARLEQUIN-COMMON-LISP:SUBFUNCTION 2 (HARLEQUIN-COMMON-LISP:SUBFUNCTION 2 SCRIPTL::CLIENT-LOOP))
Call to SIGNAL
Call to ERROR
Interpreted call to COMMON-LISP-USER::MY-COMMAND
Call to (METHOD SCRIPTL::HANDLE-CLIENT-FOR ((EQL 2) T))
Call to (HARLEQUIN-COMMON-LISP:SUBFUNCTION 2 SCRIPTL::CLIENT-LOOP)
Call to (HARLEQUIN-COMMON-LISP:SUBFUNCTION (LABELS BORDEAUX-THREADS::%BINDING-DEFAULT-SPECIALS-WRAPPER) BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS)
Call to (HARLEQUIN-COMMON-LISP:SUBFUNCTION (LABELS BORDEAUX-THREADS::%JOIN-THREAD-WRAPPER) BORDEAUX-THREADS::%MAKE-THREAD)
Call to MP::PROCESS-SG-FUNCTION

To reproduce this error we can use this minimal example:

(defun test-vector ()
  (let ((vector (scriptl::to-octets (format nil "~8,'0X" 10))))
    (fli:with-dynamic-lisp-array-pointer (ptr-var vector)
      ptr-var)))

As a quickfix, I've wrapped the TO-OCTETS body with system:in-static-area macro (which is deprecated in LW, but still works):

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defun to-octets (value)
    (system:in-static-area
      (etypecase value
        (string (string-to-utf-8-bytes value))
        ((unsigned-byte 8) (make-array 1 :element-type '(unsigned-byte 8)
                                       :initial-element value))
        (octet-vector value)
        (t (string-to-utf-8-bytes (princ-to-string value)))))))

If you wish, I'll make a patch which will run to-octets under the in-static-area macro?

Or may be it is better to convert it's result into a static vectro separately because in-static-area is deprecated?

Submitting a PR for LispWorks with whatever the best strategy is will be the most expedient thing... I'm not really set up for CL development at the moment and was never too familiar with the LW implementation.

At a glance I'm not sure why static vectors are being used at all here; I don't see them explicitly mentioned in either ScriptL or trivial-utf8, and it would seem excessive to require such. But it's early and I've only had a few sips of coffee. Perhaps this isn't the static-vectors sense.

At a glance I'm not sure why static vectors are being used at all here; I don't see them explicitly mentioned in either ScriptL or trivial-utf8, and it would seem excessive to require such. But it's early and I've only had a few sips of coffee. Perhaps this isn't the static-vectors sense.

Under the hood, when you are using write-sequence on the socket, returned by iolib's accept, it uses cffi macro with-pointer-to-vector-data before call to memcpy:

(with-pointer-to-vector-data (src-ptr src)
      (isys:memcpy
       (inc-pointer dst-ptr doff)
       (inc-pointer src-ptr soff)
       length))

And here is this macro definition for LispWorks:

(defmacro with-pointer-to-vector-data ((ptr-var vector) &body body)
  "Bind PTR-VAR to a pointer at the data in VECTOR."
  `(fli:with-dynamic-lisp-array-pointer (,ptr-var ,vector)
     ,@body))

But documentation on with-dynamic-lisp-array-pointer says the vector have to be static.

That is why when you are using write-sequence to write to iolib's socket, under the LispWorks you need to provide a statically allocated vector.

I'll create a pull request soon.

Created a pull: #11 it works for me.