Fix MCD close also closing stdout (#2931).

This commit is contained in:
Wilson Snyder 2021-06-06 19:32:48 -04:00
parent 8f2e4f6bb0
commit 31bb73e3de
6 changed files with 27 additions and 5 deletions

View File

@ -28,6 +28,7 @@ Verilator 4.203 devel
* Fix initialization of assoc in assoc array (#2914). [myftptoyman]
* Fix make support for gmake 3.x (#2920) (#2921). [Philipp Wagner]
* Fix VPI memory access for packed arrays (#2922). [Todd Strader]
* Fix MCD close also closing stdout (#2931). [Alexander Grobman]
* Fix split procedures to better respect --output-split-cfuncs (#2942). [Geza Lore]
* Fix to emit 'else if' without nesting (#2944). [Geza Lore]
* Fix part select issues in LATCH warning (#2948) (#2938). [Julien Margetts]

View File

@ -333,17 +333,20 @@ public: // But only for verilated*.cpp
}
void fdClose(IData fdi) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
const VerilatedLockGuard lock(m_fdMutex);
if ((fdi & (1 << 31)) != 0) {
if (VL_BITISSET_I(fdi, 31)) {
// Non-MCD case
IData idx = VL_MASK_I(31) & fdi;
if (VL_UNLIKELY(idx >= m_fdps.size())) return;
if (VL_UNLIKELY(idx <= 2)) return; // stdout/stdin/stderr
if (VL_UNLIKELY(!m_fdps[idx])) return; // Already free
std::fclose(m_fdps[idx]);
m_fdps[idx] = (FILE*)0;
m_fdFree.push_back(idx);
} else {
// MCD case
for (int i = 0; (fdi != 0) && (i < 31); i++, fdi >>= 1) {
// Starts at 1 to skip stdout
fdi >>= 1;
for (int i = 1; (fdi != 0) && (i < 31); i++, fdi >>= 1) {
if (fdi & VL_MASK_I(1)) {
std::fclose(m_fdps[i]);
m_fdps[i] = nullptr;
@ -375,7 +378,9 @@ private:
}
} else {
// MCD Case
for (size_t i = 0; (fdi != 0) && (i < fp.capacity()); ++i, fdi >>= 1) {
if (fdi & 1) fp.push_back(stdout);
fdi >>= 1;
for (size_t i = 1; (fdi != 0) && (i < fp.capacity()); ++i, fdi >>= 1) {
if (fdi & VL_MASK_I(1)) fp.push_back(m_fdps[i]);
}
}

View File

@ -1,2 +1,3 @@
Sean Connery was the best Bond.
To file and to stdout
*-* All Finished *-*

View File

@ -24,6 +24,8 @@ files_identical("$Self->{obj_dir}/t_sys_file_basic_mcd_test2_1.dat",
"$Self->{t_dir}/t_sys_file_basic_mcd_test2_1.dat");
files_identical("$Self->{obj_dir}/t_sys_file_basic_mcd_test2_2.dat",
"$Self->{t_dir}/t_sys_file_basic_mcd_test2_2.dat");
files_identical("$Self->{obj_dir}/t_sys_file_basic_mcd_test5.dat",
"$Self->{t_dir}/t_sys_file_basic_mcd_test5.dat");
ok(1);
1;

View File

@ -30,7 +30,7 @@ module t;
if (fd_fail != 0)
fail("Able to allocate MCD descriptor when fully utilized.");
// Return descriptor back to pool
fd_close = fd[0];
fd_close = fd[0];
$fclose(fd_close);
// Re-attempt MCD allocation; should pass at this point.
fd_success = $fopen($sformatf("%s/yet_another_file.dat", `STR(`TEST_OBJ_DIR)));
@ -76,12 +76,21 @@ module t;
int fd;
// Wide filename
fd = $fopen({`STR(`TEST_OBJ_DIR),
"some_very_large_filename_that_no_one_would_ever_use_",
"/some_very_large_filename_that_no_one_would_ever_use_",
"except_to_purposefully_break_my_beautiful_code.dat"});
if (fd == 0) fail("Long filename could not be opened.");
$fclose(fd);
end endtask
task automatic test5; begin
int fd_all;
fd_all = $fopen({`STR(`TEST_OBJ_DIR), "/t_sys_file_basic_mcd_test5.dat"});
if (fd_all == 0) fail("could not be opened.");
fd_all |= 1;
$fdisplay(fd_all, "To file and to stdout");
$fclose(fd_all);
end endtask
initial begin
// Test1: Validate file descriptor region.
@ -96,6 +105,9 @@ module t;
// Test4: Validate filename lengths
test4;
// Test5: OR with stdout
test5;
$write("*-* All Finished *-*\n");
$finish(0); // Test arguments to finish

View File

@ -0,0 +1 @@
To file and to stdout