memory scanner for Linux https://github.com/scanmem/scanmem
  • C 68%
  • Python 22.9%
  • Roff 4.8%
  • Shell 2.2%
  • M4 1.3%
  • Other 0.8%
Find a file
Rhino 6c373a6a86
gui: drive GTK from the main thread instead of the scan worker (#466)
* gui: drive GTK from the main thread, not the scan worker

Fixes the segfault-on-scan family: #427, #413, #435, #450.

GameConqueror is from the PyGTK era and still used Gdk.threads_enter() /
Gdk.threads_leave() to let a background thread touch widgets. That global
lock is gone from GTK. On a modern GTK3 the calls no longer serialize
anything, so the scan worker thread mutating widgets races the main loop
and corrupts it, which is the "Gtk-CRITICAL ... assertion failed" spew
and then the segfault people keep reporting.

There were three enter/leave sites but only one real background thread:

- progress_watcher and data_worker run on the main loop already, via
  GLib.timeout_add. Their enter/leave was dead. Removed.
- scan_thread_func is the actual worker thread. It now does only the
  blocking backend.send_command, then hands the widget updates back to
  the main loop with GLib.idle_add(self._on_scan_finished). No widget is
  touched off the main thread anymore.

command_lock is released before the idle callback, so update_scan_result
re-taking it runs on the main thread without deadlocking. source_remove
of the progress watcher also moves to the main thread where it belongs.

Also dropped the GObject.threads_init / Gdk.threads_init calls in main.
No-ops since PyGObject 3.11, they only warned on every launch (#434), and
nothing needs them once the worker is off the GTK path. This also clears
the way for GTK4, where threads_enter/leave do not exist at all.

Reproduced the crash locally with a headless driver that runs 40 scans in
a row against a memfake target while a locked cheat row makes data_worker
poll: the old code dies 4/4 runs (SIGSEGV or SIGABRT), this code is clean
3/3, zero Gtk-CRITICAL, all 40 scans finishing and returning 202 matches
each. No behaviour change to scanning, locking, or the cheat list.

* gui: address review - trim comments, use with-lock consistently

Cut the comments that only described the old threaded code, keeping the
forward-looking ones a future reader needs.

Move the remaining manual command_lock.acquire()/release() pairs to
with self.command_lock:, matching the scan worker. data_worker keeps its
non-blocking acquire(0) since with cannot express skip-if-busy, but its held
region is now under try/finally so the lock is released if the body raises.
2026-08-26 00:11:34 +02:00
.github Moved CI build from Travis to Github Actions 2023-02-13 03:45:43 +01:00
gui gui: drive GTK from the main thread instead of the scan worker (#466) 2026-08-26 00:11:34 +02:00
po scanmem 0.18 hardening and backlog fixes (#457) 2026-08-23 20:10:09 -04:00
test Use size_t instead of int for size variables. 2021-01-31 17:01:15 +01:00
.clang-format Add .clang-format for new and changed code (#467) 2026-08-24 17:35:33 -04:00
.gitignore gui: Rename *.desktop.in and *.appdata.xml.in 2018-01-21 23:28:04 +01:00
AUTHORS main: Update copyright for 2017 2017-10-13 12:05:46 +02:00
autogen.sh autogen: Run autoheader to generate config.h.in 2016-05-05 15:30:53 +02:00
build_for_android.sh scanmem 0.18 hardening and backlog fixes (#457) 2026-08-23 20:10:09 -04:00
ChangeLog ChangeLog: Link to the releases page on GitHub 2016-04-28 10:23:50 +02:00
commands.c scanmem: Introduce sub-command completion 2018-02-20 07:47:05 +01:00
commands.h scanmem: Introduce sub-command completion 2018-02-20 07:47:05 +01:00
common.c scanmem 0.18 hardening and backlog fixes (#457) 2026-08-23 20:10:09 -04:00
common.h handlers: set: Introduce and use sm_process_is_dead() 2018-10-25 09:30:53 +02:00
configure.ac Update configure.ac for cross-build support 2021-01-31 16:53:30 +01:00
COPYING 2009-12-30 21:48:05 +00:00
endianness.h libscanmem: Replace match_flags' bitfield with an enum 2017-10-07 11:56:11 +02:00
getline.c libscanmem: fix grammatical errors in comments 2017-08-08 15:28:23 +02:00
getline.h treewide: Change libscanmem license to LGPLv3 2016-11-20 14:13:18 +01:00
gpl-3.0.txt Added copies for GPL 2010-01-03 17:38:06 +00:00
handlers.c scanmem 0.18 hardening and backlog fixes (#457) 2026-08-23 20:10:09 -04:00
handlers.h handlers: clarify help list 2024-05-21 11:17:06 +02:00
interrupt.c scanmem 0.18 hardening and backlog fixes (#457) 2026-08-23 20:10:09 -04:00
interrupt.h scanmem 0.18 hardening and backlog fixes (#457) 2026-08-23 20:10:09 -04:00
lgpl-3.0.txt license: Add lgpl-3.0.txt 2016-11-20 07:12:58 +01:00
licence.h treewide: Change libscanmem license to LGPLv3 2016-11-20 14:13:18 +01:00
list.h list: Move everything to the header 2018-02-20 07:47:05 +01:00
main.c Rename main branch from "master" to "main" 2023-01-25 15:35:41 +01:00
Makefile.am handlers: set: Introduce and use sm_process_is_dead() 2018-10-25 09:30:53 +02:00
maps.c scanmem 0.18 hardening and backlog fixes (#457) 2026-08-23 20:10:09 -04:00
maps.h Introduce new option to limit regions to those that are RW 2022-05-15 00:55:06 +02:00
menu.c scanmem CLI: Add persistence of command history 2018-04-22 01:08:49 +02:00
menu.h scanmem: Move sm_getcommand() from scanmem.h to menu.h 2017-09-09 11:51:58 +02:00
NEWS scanmem 0.18 hardening and backlog fixes (#457) 2026-08-23 20:10:09 -04:00
ptrace.c scanmem 0.18 hardening and backlog fixes (#457) 2026-08-23 20:10:09 -04:00
readline.c scanmem CLI: Add persistence of command history 2018-04-22 01:08:49 +02:00
readline.h scanmem CLI: Add persistence of command history 2018-04-22 01:08:49 +02:00
README README, gui: Add README to README.md symlinks 2023-01-09 10:38:55 +01:00
README.md Rename main branch from "master" to "main" 2023-01-25 15:35:41 +01:00
scanmem.1 Introduce no ptrace option and write support for /proc/mem 2020-04-07 00:22:47 +02:00
scanmem.c fixup! Introduce no ptrace option and write support for /proc/mem 2020-04-26 01:43:58 +02:00
scanmem.h Introduce no ptrace option and write support for /proc/mem 2020-04-07 00:22:47 +02:00
scanroutines.c Use 'unsigned int' instead of unofficial alias 'uint' 2023-02-15 19:17:46 +01:00
scanroutines.h scanroutines: Introduce checking for uservalue flags at scan selection 2017-10-13 11:56:32 +02:00
sets.c sets: implement ! inversion 2017-10-05 10:30:03 +02:00
sets.h sets: Declare set_cleanup() as static inline 2017-09-23 20:14:45 +02:00
show_message.c show_message: check for terminal connection before getting pager 2019-11-19 17:29:33 -08:00
show_message.h handlers: fix bugs in help command 2020-04-07 00:12:43 +02:00
targetmem.c scanmem 0.18 hardening and backlog fixes (#457) 2026-08-23 20:10:09 -04:00
targetmem.h scanmem 0.18 hardening and backlog fixes (#457) 2026-08-23 20:10:09 -04:00
TODO move pager routines to show_messsage.c 2018-04-08 21:39:47 +02:00
value.c Fix Wextra warnings: Wsign-compare 2021-01-31 17:39:55 +01:00
value.h value: Use the C99 fixed-width formatters to print matches 2017-10-07 12:31:43 +02:00

scanmem & GameConqueror

Build Status Coverity Status

scanmem is a debugging utility designed to isolate the address of an arbitrary variable in an executing process. scanmem simply needs to be told the pid of the process and the value of the variable at several different times.

After several scans of the process, scanmem isolates the position of the variable and allows you to modify its value.

GUI

GameConqueror is a GUI front-end for scanmem, providing more features, such as:

  • Flexible syntax for searching
  • Easier and multiple variable locking
  • Better process finder
  • Memory browser/editor

See gui/README.md for more details.

Requirements

scanmem requires libreadline to read commands interactively, and /proc must be mounted. GameConqueror requirements are documented in gui/README.md.

Documentation

To read documentation:

  • man scanmem
  • man gameconqueror
  • scanmem --help
  • enter help at the scanmem prompt
  • use the interactive help of GameConqueror

Build Requirements

The build requires autotools-dev, libtool, libreadline-dev, intltool, and python.

Build and Install

To generate files required for the build:

./autogen.sh

To build with GUI:

./configure --prefix=/usr --enable-gui && make
sudo make install

To build without GUI:

./configure --prefix=/usr && make
sudo make install

scanmem and GameConqueror use static paths to libscanmem. So executing ldconfig is not required. Consider setting --libdir=/usr/lib/scanmem or --libdir=/usr/lib64/scanmem to avoid that libscanmem is in a library search path.

Run ./configure --help for more details.

Android Build

You need a standalone toolchain of Android NDK (Advanced method) to build interactive capabilities for Android. For more information, run:

./build_for_android.sh help

License:

GPLv3, LGPLv3 for libscanmem