bug-ncurses
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A Valgrind-observant ncurses


From: G. Branden Robinson
Subject: Re: A Valgrind-observant ncurses
Date: Thu, 20 Jun 2024 19:18:28 -0500

Hi Bill,

At 2024-06-20T19:49:54-0400, Bill Gray wrote:
> On 6/20/24 18:06, G. Branden Robinson wrote:
> > Doesn't printw() update curscr (via waddstr()), so by the time of
> > the next curses function call, it would no longer require this
> > buffer?
> 
>    It looks as if the buffer is re-used each time you call printw().
>    Call it once,  and the buffer is allocated;  call it again,  and
>    it's re-used (if it's already large enough) or resized (if it
>    isn't).  This logic is all encapsulated in 'safe_sprintf.c',  where
>    the buffer is 'my_buffer' and its size is 'my_length'.

Aha.  I hadn't even looked at that file before.  It illuminates much.

>    With your modification,  the buffer is allocated and used on the
>    first call,  but then immediately freed.  On the second call,  we
>    attempt to use the (now freed) pointer,  or to resize it.  Either
>    way, we'll crash.

Agreed.  It occurred to me that bad things would happen if multiple
threads called printw() (or anything that eventually called
_nc_printf_string()).  You're not supposed to do that -- at least not
without wrapping the calls with use_window(), I think.

The ncurses_threads(3x) man page could perhaps offer more explicit
multithreaded ncurses application design advice.  Either:

1.  Have one worker thread per {screen,window}, depending on which data
    structure the (n)curses function affects.
2.  Wrap window/screen-affecting (n)curses calls in
    use_window() or use_screen() as appropriate.

That's my understanding at this moment.  Could be wrong.

I'm also curious to know if ncurses use the "many readers XOR one
writer" model of mutual exclusion, or the simpler "one reader/writer at
any time" approach.  (Someone can tell me, or eventually I'll comprehend
the code.)

>    I think what has to happen instead is that,  at either endwin() or
>    delscreen(),  we call _nc_printf_string( NULL,  NULL).  If you look
>    down near the end of that function,  you can see that those
>    arguments are the magic values to cause 'my_buffer' to be freed,
>    set to NULL,  and 'my_length' set to zero.  If you _do_ restart
>    curses,  the buffer may get allocated again.

A nifty idea.

>    As Thomas notes,  endwin() is limited in what it can free,  because
>    you may restart curses.  To get Valgrind to report only five or six
>    unfreed allocations,  you have to use newterm() and,  at shutdown,
>    pass the resulting SCREEN pointer to delscreen().

If Thomas doesn't do this, I may, to get some experience with a
--disable-leaks build.

I'm curious to hear what he thinks of your idea above.

Regards,
Branden

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]