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

Sean Charles (emacstheviking) objitsu at gmail.com
Sat Jun 19 20:57:26 AEST 2021


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),
    (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)
    ).


Thanks,
I shall continue to investigate but The Boss wants me to mow the lawns first :|
Sean



%---------------------------------------------------------------------------%
%
%   LINENOISE library support.
%
    % I am using the linenoise-ng variant that supports UTF-8. It can be
    % found here, it builds and executes without error.
    % https://github.com/arangodb/linenoise-ng

:- pragma foreign_decl("C", "#include <linenoise.h>").

:- 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;
    } else {
        LineNull = 1;
    }
    printf(\"leaving, strlen() is %d\\n\", strlen(line));
    IOout = IOin;
    "
).

    % ln_free: Release a previosuly read line.
    % In order to prevent memory leaks, after the REPL has dealt with the
    % user input this must be called to hand the memory back to the pool.
    %
:- pragma foreign_proc(
    "C",
    ln_free(Line::in, IOin::di, IOout::uo),
    [will_not_throw_exception, promise_pure],
    "
    free(Line);
    IOout = IOin;
    "
).

    % ln_setup: Initialise a linenoise session.
    % I have chosen the to always have multiline modfe enabled as it is
    % probably the `expected` way it should operate by the user.
    % HistoryFile contains the name of the persisence file when ending.
    % HistoryMax contains the limit on the history size to maintain.
    %
:- pragma foreign_proc(
    "C",
    ln_setup(HistoryFile::in, HistoryMax::in, IOin::di, IOout::uo),
    [will_not_throw_exception, promise_pure],
    "
    linenoiseHistorySetMaxLen(HistoryMax);
    linenoiseSetMultiLine(1);
    linenoiseHistoryLoad((const char*)HistoryFile);
    IOout = IOin;
    "
).

    % ln_shutdown: Stop using the linenoise library.
    % HistoryFile contains the file to save session history into.
    % After saving, we then formally release the history session memory.
    %
:- pragma foreign_proc(
    "C",
    ln_shutdown(HistoryFile::in, IOin::di, IOout::uo),
    [will_not_throw_exception, promise_pure],
    "
    linenoiseHistorySave((const char*)HistoryFile);
    linenoiseHistoryFree();
    IOout = IOin;
    "
).




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


More information about the users mailing list