<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p>Hello,</p>
<p>If this is not the correct list to report a user error, I
apologize and will happily redirect my question where ever
suitable.</p>
<p>I've been using cffi to make a trivial library to libsensors
<a class="moz-txt-link-freetext" href="https://github.com/groeck/lm-sensors">https://github.com/groeck/lm-sensors</a> and am getting an odd memory
fault error when referencing a string value from a groveled
struct. After hitting my head against a wall for a day and a
half, I thought I'd ask in case it's a simple mistake.<br>
</p>
<p>Here's my information:<br>
</p>
<p>Running a 64 bit linux install. My local version of the
libsensors library is as follows:</p>
<p>
<blockquote type="cite">elliott@desktop ~ $ file
/usr/lib64/libsensors.so.4.4.0<br>
/usr/lib64/libsensors.so.4.4.0: ELF 64-bit LSB shared object,
x86-64, version 1 (SYSV), dynamically linked, stripped</blockquote>
<blockquote type="cite">elliott@desktop ~ $ sensors --version<br>
sensors version
3.4.0+git_83cafd29f28d463573750d897014ec7143217ae5 with
libsensors version
3.4.0+git_83cafd29f28d463573750d897014ec7143217ae5</blockquote>
</p>
<p>I'm using a fairly recent version of sbcl built from source that
(apparently) passed all of the tests after the build:<br>
</p>
<p> </p>
<blockquote type="cite">CL-USER> (lisp-implementation-version)<br>
"1.4.6.140-f8d5864d0"<br>
</blockquote>
<p>My version of cffi appears to be the latest:</p>
<p>
<blockquote type="cite">CL-USER> (slot-value (asdf:find-system
:cffi) 'asdf:version)<br>
"0.19.0"<br>
</blockquote>
</p>
<p>My system uses cffi-grovel and defines the following structs:</p>
<p>
<blockquote type="cite">(cstruct sensors-bus-id "sensors_bus_id"<br>
(type "type" :type :short)<br>
(nr "nr" :type :short))<br>
<br>
(cstruct sensors-chip-name "sensors_chip_name"<br>
(prefix "prefix" :type :string)<br>
(bus "bus" :type (:struct sensors-bus-id))<br>
(address "addr" :type :int)<br>
(path "path" :type :string))<br>
</blockquote>
</p>
<p>These are based upon the definitions in sensors/sensors.h:
<a class="moz-txt-link-freetext" href="https://github.com/groeck/lm-sensors/blob/master/lib/sensors.h">https://github.com/groeck/lm-sensors/blob/master/lib/sensors.h</a></p>
After asdf loading the system, the following groveler definitions
are created (had to dig these out of the cached build files):<br>
<blockquote type="cite">(cffi:defcstruct (sensors-bus-id :size 4)<br>
(type :short :offset 0)<br>
(nr :short :offset 2))<br>
(cl:defconstant size-of-sensors-bus-id (cffi:foreign-type-size
'(:struct sensors-bus-id)))<br>
(cffi:defcstruct (sensors-chip-name :size 24)<br>
(prefix :string :offset 0)<br>
(bus (:struct sensors-bus-id) :offset 8)<br>
(address :int :offset 12)<br>
(path :string :offset 16))<br>
(cl:defconstant size-of-sensors-chip-name (cffi:foreign-type-size
'(:struct sensors-chip-name)))</blockquote>
All of the above appears to be correct, so I proceed to load the
library:<br>
<blockquote type="cite">(define-foreign-library libsensors<br>
(:unix (:or "libsensors.so.4" "libsensors.so"))<br>
(t (:default "libsensors.so")))<br>
(use-foreign-library libsensors)<br>
</blockquote>
No issues, so I define a c function from the c header file that
parses a sensor chip name-string into a struct:<br>
<br>
<blockquote type="cite">(defcfun ("sensors_parse_chip_name"
cffi-sensors-parse-chip-name) :int<br>
"Parse a chip name to the internal representation. Return 0 on
success, <0 on error."<br>
(orig-name :string) <br>
(res (:pointer (:struct sensors-chip-name))))</blockquote>
<br>
Which is based upon the following header function declaration:<br>
<br>
<blockquote type="cite">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<span class="pl-k">int</span> <span class="pl-smi">sensors_parse_chip_name</span>(<span
class="pl-k">const</span> <span class="pl-k">char</span>
*orig_name, sensors_chip_name *res);</blockquote>
<br>
Then I implement a simple call to print out the parsed values (not
including the bus):<br>
<br>
<blockquote type="cite">(defun test-sensors-parse-chip-name
(string) <br>
(with-foreign-object (name '(:struct sensors-chip-name))<br>
(unless (= 0 (cffi-sensors-parse-chip-name string name))<br>
(error "Failed to parse: ~A" string))<br>
(with-foreign-slots ((prefix address path)<br>
name<br>
(:struct sensors-chip-name))<br>
(format t "~%Prefix: '~A'" prefix)<br>
(format t "~%Address: '~A'" address)<br>
(format t "~%Path: '~A'" path))))</blockquote>
<br>
The above when executed gives the following output before the error:<br>
<br>
<blockquote type="cite">CL-LMSENSORS>
(test-sensors-parse-chip-name "atk0110-acpi-0")<br>
<br>
Prefix: 'atk0110'<br>
Address: '0'</blockquote>
<br>
And once it tries to access the path variable, it gives the
following error (sorry a lot rolls off the screen):<br>
<br>
<blockquote type="cite">Unhandled memory fault at #xE71B7.<br>
[Condition of type SB-SYS:MEMORY-FAULT-ERROR]<br>
<br>
Restarts:<br>
0: [RETRY] Retry SLIME REPL evaluation request.<br>
1: [*ABORT] Return to SLIME's top level.<br>
2: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING
{1002207F93}>) <br>
<br>
Backtrace:<br>
0: (CFFI::FOREIGN-STRING-LENGTH #.(SB-SYS:INT-SAP #X000E71B7)
:ENCODING :UTF-8 :OFFSET 0)<br>
Locals:<br>
#:.DEFAULTING-TEMP. = :UTF-8<br>
#:.DEFAULTING-TEMP.#1 = 0<br>
#:N-SUPPLIED-0 = 1<br>
POINTER = #.(SB-SYS:INT-SAP #X000E71B7)<br>
1: (FOREIGN-STRING-TO-LISP #.(SB-SYS:INT-SAP #X000E71B7) :OFFSET
0 :COUNT NIL :MAX-CHARS 4611686018427387900 :ENCODING :UTF-8$<br>
Locals: <br>
#:.DEFAULTING-TEMP. = 0<br>
#:.DEFAULTING-TEMP.#1 = NIL<br>
#:.DEFAULTING-TEMP.#2 = 4611686018427387900<br>
#:.DEFAULTING-TEMP.#3 = :UTF-8<br>
ENCODING = :UTF-8<br>
#:N-SUPPLIED-0 = 1<br>
POINTER = #.(SB-SYS:INT-SAP #X000E71B7)<br>
2: ((:METHOD TRANSLATE-FROM-FOREIGN (T
CFFI::FOREIGN-STRING-TYPE)) #.(SB-SYS:INT-SAP #X000E71B7)
#<CFFI::FOREIGN-STRING-TYPE $<br>
3: (TEST-SENSORS-PARSE-CHIP-NAME "atk0110-acpi-0") </blockquote>
My guess is I'm not defining the (:struct sensors-chip-name)
correctly, so that when sensors_parse_chip_name writes values into
the struct, it somehow overlaps into the path string. <br>
<br>
When looking at the source for sensors_parse_chip_name I've noticed
that it does not set or access the path value at all. So I decided
to write a small c program to test the native behavior:<br>
<br>
<blockquote type="cite">elliott@desktop ~ $ cat test-sensors.c<br>
#include <stdio.h><br>
#include <stdlib.h><br>
#include "sensors/sensors.h"<br>
<br>
int main( ) {<br>
<br>
//sensors_init( NULL );<br>
<br>
struct sensors_chip_name name;<br>
<br>
int return_value = sensors_parse_chip_name( "atk0110-acpi-0",
&name);<br>
if ( return_value != 0 ) {<br>
printf( "Failed to get a good return value." );<br>
exit( return_value );<br>
}<br>
<br>
printf( "Printing the prefix: '%s'\n", name.prefix );<br>
printf( "Address: '%i'\n", name.addr ); <br>
printf( "Printing path value: '%s'\n", name.path );<br>
printf ("\n exiting..." );<br>
<br>
exit( 0 );<br>
} <br>
elliott@desktop ~ $ gcc test-sensors.c -l sensors -o test-sensors<br>
elliott@desktop ~ $ ./test-sensors <br>
Printing the prefix: 'atk0110'<br>
Address: '0'<br>
Printing path value: ''<br>
<br>
exiting... <br>
</blockquote>
No problems there, so I assume that the issue is all my lack of
cffi-fu training. Any pointers (yes, pun intended) would be
appreciated... sorry for such a long read, but I hope it helps to
have the background. At the very least it helped me to frame the
issue in my mind by writing this.<br>
<br>
Regards,<br>
Elliott<br>
<br>
</body>
</html>