Skip to content

Commit

Permalink
initial valgrind support
Browse files Browse the repository at this point in the history
  • Loading branch information
thomcc committed Jul 18, 2023
1 parent 076988c commit a936527
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 2 deletions.
19 changes: 19 additions & 0 deletions cargo-pgrx/src/command/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ pub(crate) struct Init {
base_testing_port: Option<u16>,
#[clap(long, help = "Additional flags to pass to the configure script")]
configure_flag: Vec<String>,
/// Compile PostgreSQL with the necessary flags to detect a good amount of
/// memory errors when run under Valgrind.
///
/// Building PostgreSQL with these flags requires that Valgrind be
/// installed, but the resulting build is usable without valgrind.
#[clap(long)]
valgrind: bool,
}

impl CommandExecute for Init {
Expand Down Expand Up @@ -280,8 +287,20 @@ fn configure_postgres(pg_config: &PgConfig, pgdir: &PathBuf, init: &Init) -> eyr
let mut configure_path = pgdir.clone();
configure_path.push("configure");
let mut command = std::process::Command::new(configure_path);
// Some of these are redundant with `--enable-debug`.
let mut existing_cppflags = std::env::var("CPPFLAGS").unwrap_or_default();
existing_cppflags += " -DMEMORY_CONTEXT_CHECKING=1 -DMEMORY_CONTEXT_CHECKING=1 \
-DCLOBBER_FREED_MEMORY=1 -DRANDOMIZE_ALLOCATED_MEMORY=1 ";
if init.valgrind {
// `-Og` turns on light optimizations, which is useful for getting
// something usable. `USE_VALGRIND` allows valgrind to understand PG's
// memory context shenanigans.
let valgrind_flags = "-DUSE_VALGRIND=1 -Og ";
existing_cppflags += valgrind_flags;
}

command
.env("CPPFLAGS", existing_cppflags)
.arg(format!("--prefix={}", get_pg_installdir(pgdir).display()))
.arg(format!("--with-pgport={}", pg_config.port()?))
.arg("--enable-debug")
Expand Down
38 changes: 36 additions & 2 deletions pgrx-tests/src/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,8 +446,31 @@ fn start_pg(loglines: LogLines) -> eyre::Result<String> {
wait_for_pidfile()?;

let pg_config = get_pg_config()?;
let mut command =
Command::new(pg_config.postmaster_path().wrap_err("unable to determine postmaster path")?);
let postmaster_path =
pg_config.postmaster_path().wrap_err("unable to determine postmaster path")?;

let mut command = if use_valgrind() {
let mut cmd = Command::new("valgrind").args([
"--leak-check=no",
"--gen-suppressions=all",
"--time-stamp=yes",
"--error-markers=VALGRINDERROR-BEGIN,VALGRINDERROR-END",
"--log-file=target/pg-valgrind-%p.log",
"--trace-children=yes",
]);
// Try to provide a suppressions file, we'll likely get false positives
// if we can't, but that might be better than nothing.
if let Ok(path) = valgrind_suppressions_path(&pg_config) {
if path.exists() {
cmd.arg(format!("--suppressions={}", path.display()));
}
}

cmd.arg(postmaster_path);
cmd
} else {
Command::new(postmaster_path)
};
command
.arg("-D")
.arg(get_pgdata_path()?.to_str().unwrap())
Expand All @@ -469,6 +492,13 @@ fn start_pg(loglines: LogLines) -> eyre::Result<String> {
Ok(session_id)
}

fn valgrind_suppressions_path(pg_config: &PgConfig) -> Result<PathBuf, eyre::Report> {
let mut home = Pgrx::home()?;
home.push(pg_config.version()?);
home.push("src/tools/valgrind.supp");
Ok(home)
}

fn wait_for_pidfile() -> Result<(), eyre::Report> {
const MAX_PIDFILE_RETRIES: usize = 10;

Expand Down Expand Up @@ -756,3 +786,7 @@ fn find_on_path(program: &str) -> Option<PathBuf> {
let paths = std::env::var_os("PATH")?;
std::env::split_paths(&paths).map(|p| p.join(program)).find(|abs| abs.exists())
}

fn use_valgrind() -> bool {
std::env::var_os("USE_VALGRIND").is_some()
}

0 comments on commit a936527

Please sign in to comment.