Subject: Re: [clisp-list] sigaction for linux.lisp

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Mon Mar 11 04:19:17 2002

Hi,

Peter Wood wrote:

> A peculiarity which may be a bug in the ffi was this: The sa_flags
> member in a sigaction structure is declared (in C) as an int.  However
> Clisp reported that it could not coerce SA_RESETHAND (reset to default
> handler) to an ffi:int. [...]
> SA_RESETHAND is defined as #x80000000.  Changing ffi:int to ffi:uint32
> in the ffi definition for the sigact struct solved the problem.  Why
> does it work in C if SA_RESETHAND is too large.  There may be a
> problem here, or am I missing something.

The essence is: get the C programmers to get their declarations right!
File a bug-report to Linux, Sun, BSD or whoever.

You know, "unsigned int" is just so much more to type than "int" :-( It's a typical C disease to say int when they mean unsigned, and int when they mean int32. At least, C people finally managed to provide size_t and offset_t as unsigned types!
0x8000000 is an unsigned AFAIK. It's typical of C not to complain that it doesn't fit into a *signed* 32bit int.

Don't even think of having CLISP silently coerce the range -2^31 to 2^32-1 into 0-2^32-1!
It will give you headaches as follows: on input, you may pass (- (expt 2 31)), but on return, you'll get (- (expt 2 32) -1), or vice versa. Then people will complain that (= input output) works in typical C code (minus a warning from better compilers) whereas it caused them hours of debugging Lisp code.

The C declaration is at fault, not Lisp, nor the FFI!
C programmers ought to use unsigned types whereever they makes sense, and esp. for bit masks.

> Obviously, the sigaction stuff has not been _rigorously_ tested.

Your three definitions sigaction-new/old/query only require only two. You could merge sigaction-new and query. Please advantage of c-ptr-null (instead of c-ptr) to pass NIL on input.

Sadly, there's no way to pass in a NULL pointer for :out parameters. You still need two different DEF-CALL-OUT forms for that.

>  You should probably be
> careful in case there is some unknown problem.

Bruno Haible should be able to comment upon the ability to run Lisp code from within a signal handler on the various UNIX platforms. It may get hairy.

> a sigaction struct can be (in C) either a pointer to a function, or an
> int! [...] If it was a
> c function, I would split it into 2 cases, for handling the different
> types, but what does one do when it's a struct!?
Good problem. ffi:c-union wont's help here, since CLISP says "Conversion to and from Lisp assumes that a value is to be viewed as being of c-type1."

It's a known (to me) FFI problem. What I had done in AFFI would have been to selectively dereference the slots. I believe this requires an extension to FOREIGN-VARIABLES in the current FFI. Redesign of the FFI is an open topic. FOREIGN-CALL-OUT should provide means to return FOREIGN-VARIABLE types instead of converting immediately to Lisp objects. Then you could use CAST and FOREIGN-VALUE.

Regards,
	Jorg Hohle.

---

From: Peter Wood <[email-masked]>
Date: Mon Mar 11 10:05:05 2002

Hi,

> C programmers ought to use unsigned types whereever they makes sense, and esp. for bit masks.

OK :-)

> Your three definitions sigaction-new/old/query only require only two. You could merge sigaction-new and query. Please advantage of c-ptr-null (instead of c-ptr) to pass NIL on input.

Here is the way I defined them, followed by the way I assume you are
saying c-ptr-null should be used, but which doesn't work!

(def-c-call-out sigaction-new
  (:name "sigaction")
  (:arguments (sig int)
	      (act (c-ptr sigaction) :in :alloca)
	      (null c-string)) ;nil
  (:return-type int))
;eg (sigaction SIGINT newhandler nil) => 0

(def-c-call-out sigaction-query
  ;if 2nd & 3rd args are null, query if signal SIG is valid
  (:name "sigaction")
  (:arguments (sig int)
	      (null c-string) ;nil
	      (null c-string)) ;null
  (:return-type int))
;eg (linux:sigaction-query linux:SIGINT nil nil) => 0

;;this _doesn't_ work

(def-c-call-out sigaction-new-or-query
  (:name "sigaction")
  (:arguments (sig int)
              (act (c-ptr-null sigaction) :in :alloca)
              (null c-string))
  (:return-type int))

I get an error on attempted compilation as follows:

***invalid ffi type (c-ptr-null sigaction)

I get the same error if I leave out the :in :alloca, and (other)
predictable errors when I use it in ways which don't conform to the
documentation.

And I don't know how else I could write it to make use of c-ptr-null.
The documentation says that c-ptr-null is like c-ptr but that C NULL
corresponds to Lisp NIL.  The 'declaration' is (c-ptr-null c-type)
according to the impnotes.

How should it be used?

Regards,
Peter

---

From: Peter Wood <[email-masked]>
Date: Mon Mar 11 12:50:02 2002

> saying c-ptr-null should be used, but which doesn't work!

...

> ***invalid ffi type (c-ptr-null sigaction)

But this does:

 (def-c-call-out sigaction-new-or-query
   (:name "sigaction")
   (:arguments (sig int)
               (act (c-ptr-null nil) :in :alloca)
               (null c-string))
   (:return-type int))

And the reason I was getting the error message described, was that I
had forgotten to add c-ptr-null to the list of substitutions in
linux.lisp.  AAAAARGH.

Thanks for your suggestions - this has also solved (one of the)
problems which I am having in a module I am writing.

Regards,
Peter