bug-ncurses
[Top][All Lists]
Advanced

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

unlock of an unlocked mutex


From: Tom de Vries
Subject: unlock of an unlocked mutex
Date: Thu, 7 Jul 2022 18:01:37 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.9.0

Hi,

After building gdb with gcc -fsanitize=thread, I ran into a problem in ncurses.

It's easy to reproduce using this small program:
...
$ cat test.c
#include <stdlib.h>
#include <stdio.h>
#include <curses.h>

int
main (void)
{
  newterm (NULL, stdout, stdin);

  return 0;
}
...

Compile like so:
...
$ gcc test.c -fsanitize=thread -lncurses
...
and then run:
...
$ ./a.out 2>&1 | tee LOG
==================
WARNING: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread) (pid=5864)
    #0 pthread_mutex_unlock <null> (libtsan.so.0+0x3e4ca)
#1 newterm ../ncurses/./base/lib_newterm.c:357 (libncurses.so.6+0x141c4)
    #2 __libc_start_main <null> (libc.so.6+0x352bc)

Location is global '_nc_globals' of size 712 at 0x7f9c4b258bc0 (libtinfo.so.6+0x00000022dd98)

  Mutex M10 (0x7f9c4b258d98) created at:
    #0 pthread_mutex_init <null> (libtsan.so.0+0x4c483)
#1 _nc_mutex_init ../ncurses/./tinfo/lib_data.c:351 (libtinfo.so.6+0xcfee)
    #2 __libc_start_main <null> (libc.so.6+0x352bc)

SUMMARY: ThreadSanitizer: unlock of an unlocked mutex (or by a wrong thread) (/usr/lib64/libtsan.so.0+0x3e4ca) in pthread_mutex_unlock
==================
ThreadSanitizer: reported 1 warnings
...

Using this gdb session:
...
$ gdb -q -batch a.out -ex "set breakpoint pending on" -ex "b _nc_mutex_lock" -ex "b _nc_mutex_unlock" -ex "b _nc_mutex_init" -ex "b _nc_mutex_trylock" -ex run -ex "c" -ex c -ex c -ex c -ex c -ex c -ex c -ex c -ex c -ex c -ex c -ex c -ex c -ex c 2>&1 | tee gdb-log.txt
...
I generated attached gdb-log.txt.

I think the sanitizer complains about this lock:
...
$ grep 472 gdb-log.txt
Breakpoint 1, _nc_mutex_lock (obj=0x7ffff5ab9d98 <_nc_globals+472>) at ../ncurses/./tinfo/lib_data.c:358 Breakpoint 3, _nc_mutex_init (obj=0x7ffff5ab9d98 <_nc_globals+472>) at ../ncurses/./tinfo/lib_data.c:345 Breakpoint 2, _nc_mutex_unlock (obj=0x7ffff5ab9d98 <_nc_globals+472>) at ../ncurses/./tinfo/lib_data.c:374
...

Which is the 'prescreen' lock:
...
$ gdb -q -batch a.out -ex run -ex "print &_nc_globals.mutex_prescreen" 2>&1 | grep 472
$1 = (pthread_mutex_t *) 0x7ffff5ab9d98 <_nc_globals+472>
...

What happens is:
- we lock the mutex
- we init the mutex, which destroys the locked mutex, and creates an
  unlocked one
- we unlock the unlocked mutex

I wonder if this fixes it:
...
diff --git a/ncurses/base/lib_newterm.c b/ncurses/base/lib_newterm.c
index bba97ba1..e1c78f50 100644
--- a/ncurses/base/lib_newterm.c
+++ b/ncurses/base/lib_newterm.c
@@ -362,6 +362,7 @@ NCURSES_EXPORT(SCREEN *)
 newterm(const char *name, FILE *ofp, FILE *ifp)
 {
     SCREEN *rc;
+    _nc_init_pthreads();
     _nc_lock_global(prescreen);
     START_TRACE();
     rc = NCURSES_SP_NAME(newterm) (CURRENT_SCREEN_PRE, name, ofp, ifp);
...

Thanks,
- Tom

Attachment: gdb-log.txt
Description: Text document


reply via email to

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