[m-users.] Segmentation violation on FFI wrapper for linenoise-ng

Sean Charles (emacstheviking) objitsu at gmail.com
Sat Jun 19 23:17:00 AEST 2021


I also now wonder if ‘::out’ ids the correct type seeing how the memory was not allocated by mercury. I am going to read closely the FFI documentation again and the mode declarations and see if I have overlooked something, being a n00b at this still the finer points have yet to present themselves fully to me.

At times like this, they do!
Sean


> On 19 Jun 2021, at 14:15, Sean Charles (emacstheviking) <objitsu at gmail.com> wrote:
> 
> RESOLVED:
> 
> :- pragma foreign_proc(
>     "C",
>     ln_read(Prompt::in, Line::out, LineNull::out, IOin::di, IOout::uo),
>     [will_not_throw_exception, promise_pure],
>     "
>     char* line = linenoise((const char*)Prompt);
>     if (line) {
>         linenoiseHistoryAdd(line);
>         LineNull = 0;
>         Line = line;
>     } else {
>         LineNull = 1;
>         Line = \"\";
>     }
>     IOout = IOin;
>     "
> ).
> 
> Use of CTRL-D now behaves itself. I guess I was not smart enough to fully grok your comment first time around Julien! I still don’t know —why— it cures the issue as I wasn’t using that variable (Line) if LineNull indicated it was not to be trusted… is it something internal in the FFI interface, I have no clue on that.
> 
> Thanks all,
> Sean
> 
> 
> 
>> On 19 Jun 2021, at 13:31, Julien Fischer <jfischer at opturion.com <mailto:jfischer at opturion.com>> wrote:
>> 
>> 
>> Hi Sean,
>> 
>> On Sat, 19 Jun 2021, Sean Charles (emacstheviking) wrote:
>> 
>>> It all works beautifully, as expected but when I use CTRL-D it balks with this output:
>>> *** Mercury runtime: caught segmentation violation ***
>>> cause: address not mapped to object
>>> address involved: 0x0
>>> This may have been caused by a stack overflow, due to unbounded recursion.
>>> exiting from signal handler
>>> [1]    68417 segmentation fault  ./felt -r
>>> I have attached the full FFI code at the end. I’ve tried to work it through. The source code for the input function is here:
>>> I studied the source code, it is using fgets() which returns NULL on end-of-file and I thought I was managing that just fine!
>>> Does Mercury have something to with this e.g. a SIGINT handler or something that might be clashing with the linenoise-ng code I wonder ?
>>> The calling code in my REPL loop is as follows:
>>> :- pred run_loop(
>>>     command_line.felt_options::in,
>>>     replcon::in, replcon::out,
>>>     io::di, io::uo) is det.
>>> run_loop(Options, !Repl, !IO) :-
>>>     ln_read(prompt, Line, LineNull, !IO),
>>>     io.format("LNG: NULL:%d, len:%d, \n", [i(LineNull), i(length(Line))], !IO),
>> 
>> Ok, so we are doing stuff with the variable Line here ...
>> 
>>>     (if LineNull = 1 then
>>>         io.format("\n%sBe excellent to one another.\n",
>>>              [s(prompt)], !IO)
>>>     else
>>>         execute(Line, !Repl, !IO),
>>>         run_loop(Options, !Repl, !IO)
>>>     ).
>> 
>> ...
>> 
>>> :- pred ln_setup(string::in, int::in, io::di, io::uo) is det.
>>> :- pred ln_shutdown(string::in, io::di, io::uo) is det.
>>> :- pred ln_read(string::in, string::out, int::out, io::di, io::uo) is det.
>>> :- pred ln_free(string::in, io::di, io::uo) is det.
>>>     % ln_read: Reads and returns a single line.
>>>     % Line is unified with whataver the library read from stdin.
>>>     % LineNull is unified with 1 if NULL(CTRL+D) is detected, else 0.
>>>     % If the line is not empty then we automatically add it to the history.
>>>     %
>>> :- pragma foreign_proc(
>>>     "C",
>>>     ln_read(Prompt::in, Line::out, LineNull::out, IOin::di, IOout::uo),
>>>     [will_not_throw_exception, promise_pure],
>>>     "
>>>     char* line = linenoise((const char*)Prompt);
>>>     if (line) {
>>>         linenoiseHistoryAdd(line);
>>>         LineNull = 0;
>>>         Line = line;
>> 
>> ... which is set to a value in this branch , but ...
>> 
>>>     } else {
>>>         LineNull = 1;
>> 
>> ... not in this one.
>> 
>> 
>>>     }
>>>     printf(\"leaving, strlen() is %d\\n\", strlen(line));
>>>     IOout = IOin;
>>>     "
>> 
>> I'm not familiar with the linenoise library, but I am assuming that the
>> function linenoise() returns NULL on EOF?
>> 
>> Julien.
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20210619/783ba1bb/attachment-0001.html>


More information about the users mailing list