Skip to content

Commit a8185af

Browse files
author
Zanthoxylum
committed
Fix: use threadsafe death tests in DFPT suites to avoid fork-in-threaded-process deadlock
MODULE_DFPT_pw_run_test timed out (1700 s) in the gnu Test CI job: the two irrep-loop tests run first execute OpenMP regions, so with the job's OMP_NUM_THREADS=2 the process is multithreaded when the third test (dftu-reservation EXPECT_EXIT) forks. The default fast-style child then deadlocks on exit and the parent waits forever (reproduced locally under OMP_NUM_THREADS=2: gtest warns 'detected 2 threads' and hangs). Switch all three DFPT death tests to the fork+exec threadsafe style (same pattern as module_container tensor_test). For the pw_run test also bridge std::cout to std::cerr inside the death statement: WARNING_QUIT prints the NOTICE block to stdout, while death tests match the child's stderr; the old CaptureStdout+HasSubstr assertion cannot see the re-exec child's output. Verified under OMP_NUM_THREADS=2: pw_run 3/3 in 0.3 s (previously indefinite hang), kq_basis 5/5, pert_serial 8/8, and the full MODULE_DFPT ctest batch 8/8.
1 parent 7e6f180 commit a8185af

3 files changed

Lines changed: 13 additions & 7 deletions

File tree

source/source_pw/module_dfpt/test/dfpt_kq_basis_test.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ TEST_F(DFPTKQBasisTest, TranslationInvarianceOfKQ)
383383

384384
TEST_F(DFPTKQBasisTest, InvalidOrMismatchedBaseIsRejected)
385385
{
386+
::testing::FLAGS_gtest_death_test_style = "threadsafe";
386387
// null providers: valid-but-empty basis
387388
ModuleDFPT::DFPT_KQ_Basis kq;
388389
kq.init(nullptr, nullptr, ModuleBase::Vector3<double>(0.0, 0.0, 0.0), 0);

source/source_pw/module_dfpt/test/dfpt_pw_run_test.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ TEST_F(DFPT_PWRunTest, DielectricAndBornAreExposed)
214214

215215
TEST_F(DFPT_PWRunTest, DftuReservationWithProviderRejectsInit)
216216
{
217+
// the preceding irrep-loop tests run OpenMP regions, so the default
218+
// "fast" fork-based death test can deadlock in the multithreaded child
219+
// (CI: OMP_NUM_THREADS=2); use the fork+exec style instead
220+
::testing::FLAGS_gtest_death_test_style = "threadsafe";
217221
// DFT+U reservation (U0): the ground state wires a provider when
218222
// dft_plus_u is enabled upstream, and PW-basis DFT+U actually runs in
219223
// the ground state now. Since every DFPT U hook (cal_docc, build_dv_u,
@@ -227,11 +231,11 @@ TEST_F(DFPT_PWRunTest, DftuReservationWithProviderRejectsInit)
227231
Plus_U_Base dftu;
228232
dfpt.set_qmesh(1, 1, 1);
229233
psi::Psi<std::complex<double>> psi;
230-
testing::internal::CaptureStdout();
231-
EXPECT_EXIT(dfpt.init(ucell, psi, nullptr, nullptr, nullptr, std::vector<double>(),
232-
ModuleBase::matrix(), ModuleBase::matrix(), nullptr, 1.0, 15.0, &dftu),
233-
::testing::ExitedWithCode(1),
234-
"");
235-
const std::string output = testing::internal::GetCapturedStdout();
236-
EXPECT_THAT(output, testing::HasSubstr("DFT+U with DFPT is not supported"));
234+
// death tests match the child's stderr, while WARNING_QUIT writes the
235+
// NOTICE block to std::cout; bridge the two inside the statement
236+
EXPECT_EXIT({
237+
std::cout.rdbuf(std::cerr.rdbuf());
238+
dfpt.init(ucell, psi, nullptr, nullptr, nullptr, std::vector<double>(),
239+
ModuleBase::matrix(), ModuleBase::matrix(), nullptr, 1.0, 15.0, &dftu);
240+
}, ::testing::ExitedWithCode(1), "DFT\\+U with DFPT is not supported");
237241
}

source/source_pw/module_dfpt/test_serial/dfpt_pert_serial_test.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ TEST_F(DFPTPertSerialTest, DVnlDtauMatchesOperatorFiniteDifference)
624624

625625
TEST_F(DFPTPertSerialTest, NonlocalPathRejectsUltrasoft)
626626
{
627+
::testing::FLAGS_gtest_death_test_style = "threadsafe";
627628
MakeNCAtom();
628629
ucell_.atoms[0].ncpp.tvanp = true;
629630
const int npwk = pw_wfc_.npwk[0];

0 commit comments

Comments
 (0)