[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