Conversation
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... 📒 Files selected for processing (10)
Tip You can generate walkthrough in a markdown collapsible section to save space.Enable the WalkthroughThe pull request replaces the Pathvirt filesystem path-virtualization plugin with a new PathTranslator plugin offering environment-driven path remapping. The Pathvirt plugin and its declarations are removed from build configurations and source. The new PathTranslator plugin is added to the build system and implements path translation via DMTCP_PATH_MAPPING environment variable. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant App as Application
participant PM as PluginManager
participant PT as PathTranslator Plugin
participant Env as Environment
rect rgb(200, 220, 255)
Note over PT,Env: INIT/RESTART Phase
PM->>PT: pathTranslator_EventHook(INIT)
PT->>Env: read DMTCP_PATH_MAPPING
PT->>PT: populate pathMapping unordered_map
end
rect rgb(220, 200, 255)
Note over PT,Env: Path Translation Phase
App->>PM: dmtcp event VIRTUAL_TO_REAL_PATH
PM->>PT: pathTranslator_VirtualToReal(data)
PT->>PT: find matching prefix in pathMapping
PT->>PT: replace virtual prefix with real prefix
PT->>data: write translated path
end
rect rgb(200, 255, 220)
Note over PT,Env: Checkpoint/Restart Phases
App->>PM: PRE_EXEC
PM->>PT: pathTranslator_PrepareForExec
PT->>Env: serialize pathMapping to environment
App->>PM: POST_EXEC
PM->>PT: pathTranslator_PostExec
PT->>Env: deserialize pathMapping from environment
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~35 minutes The changes involve a substantial new plugin implementation (~400+ lines), coordinated removal of the old Pathvirt plugin across multiple files, and build system updates. However, the changes follow a clear, consistent pattern (environment-variable-driven initialization, prefix-based translation), and the removed Pathvirt plugin is cleanly excised without interdependencies left behind. Minor changes to fileconnection.cpp and autoconf files add modest complexity. Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
2fdac7e to
0c9ab1d
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/dmtcpplugin.cpp (1)
381-399: Pointer-size bug in loop bound; use actual buffer size.
while (start_ptr - env_buf < (int)sizeof(env_buf))usessizeof(env_buf)whereenv_bufis a pointer, so the loop bound is 4/8 bytes, breaking scanning and potentially causing incorrect results. Usesize(the allocated buffer length) instead. Also ensure key match ends at '=' to avoid prefix collisions and avoid leavingvalueunterminated on truncation.Apply:
- while (start_ptr - env_buf < (int)sizeof(env_buf)) { + while ((size_t)(start_ptr - env_buf) < size) { pos = NULL; - if (strncmp(start_ptr, name, namelen) == 0) { - if ((pos = strchr(start_ptr, '='))) { - strncpy(value, pos + 1, maxvaluelen); - if (strlen(pos + 1) >= maxvaluelen) { + if (strncmp(start_ptr, name, namelen) == 0 && start_ptr[namelen] == '=') { + if ((pos = strchr(start_ptr, '='))) { + size_t vlen = strlen(pos + 1); + if (vlen >= maxvaluelen) { rc = RESTART_ENV_TOOLONG; // value does not fit in the // user-provided value buffer break; - } + } + // safe copy with NUL termination + snprintf(value, maxvaluelen, "%s", pos + 1); } rc = RESTART_ENV_SUCCESS; break; }config.sub (1)
980-983: Typo in variable name breaks default OS assignment.
basic_os=${Basic_os:-unicos}usesBasic_os(wrong case). This leavesbasic_osunchanged and can produce wrong triplets.- basic_os=${Basic_os:-unicos} + basic_os=${basic_os:-unicos}config.guess (1)
1-80: Sync config.guess (2022-01-09) and config.sub (2022-01-03) from the same upstream commit.The two files have different timestamps (6 days apart in January 2022), confirming they originate from different upstream commits. This creates risk of tuple drift—architecture and OS handling may differ between the scripts. Update both files to match the same upstream version, or explicitly document why intentional mismatch is acceptable.
🧹 Nitpick comments (2)
config.sub (1)
1076-1080: Intentional misspelling?Pattern
athalon_*-*likely intends to catch mis-spelled “athlon”. If intentional, OK; otherwise remove to avoid unintended matches.src/plugin_pathtranslator.cpp (1)
21-25: Clarify ENV format in comment.The example currently shows colon-only separation. Update to:
"/path/a:/path/a_new;/path/b:/path/b_new;/path/b/c:/path/c_new".
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
config.guess(28 hunks)config.sub(21 hunks)configure(3 hunks)plugin/Makefile.am(0 hunks)plugin/Makefile.in(1 hunks)plugin/pathvirt/pathvirt.cpp(0 hunks)plugin/pathvirt/pathvirt.h(0 hunks)src/Makefile.am(1 hunks)src/Makefile.in(6 hunks)src/dmtcpplugin.cpp(1 hunks)src/plugin/ipc/file/fileconnection.cpp(1 hunks)src/plugin_pathtranslator.cpp(1 hunks)src/pluginmanager.cpp(2 hunks)
💤 Files with no reviewable changes (3)
- plugin/Makefile.am
- plugin/pathvirt/pathvirt.h
- plugin/pathvirt/pathvirt.cpp
🧰 Additional context used
🧬 Code graph analysis (2)
src/pluginmanager.cpp (1)
src/plugin_pathtranslator.cpp (2)
dmtcp_PathTranslator_PluginDescr(162-166)dmtcp_PathTranslator_PluginDescr(163-163)
src/plugin_pathtranslator.cpp (1)
src/dmtcpplugin.cpp (2)
dmtcp_get_restart_env(331-410)dmtcp_get_restart_env(331-334)
🪛 Clang (14.0.6)
src/plugin_pathtranslator.cpp
[error] 2-2: 'dirent.h' file not found
(clang-diagnostic-error)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (12)
plugin/Makefile.in (1)
187-187: LGTM!Correct removal of pathvirt dependency tracking as part of the pathvirt plugin removal.
src/Makefile.in (1)
213-215: LGTM!Standard Makefile.in integration for the new plugin_pathtranslator.cpp source file. The changes correctly add the object file, dependency tracking, and cleanup rules.
Also applies to: 263-277, 995-995, 1322-1322, 1430-1430
src/Makefile.am (1)
171-171: LGTM!Correctly adds plugin_pathtranslator.cpp to the libdmtcp.so source list.
src/pluginmanager.cpp (1)
29-29: Verify that PathTranslator should be registered first.The PathTranslator plugin is now the first plugin to be registered. According to the comments (lines 98-106), plugin order matters for the layered architecture—events before checkpoint execute in registration order, while resume/restart events execute in reverse. Confirm that path translation should occur first (earliest in pre-checkpoint events, latest in restart events).
Also applies to: 61-61
src/plugin/ipc/file/fileconnection.cpp (1)
467-467: Confirm therefreshPath()duplication at lines 467 and 484 is intentional.The code structure confirms the review comment's concern: for checkpointed non-batch-queue files,
refreshPath()executes unconditionally at line 467, then again at line 484 in theelseblock. While this duplication may be intentional (e.g., early path resolution for all files, then a second resolution before file creation for checkpointed non-batch-queue files), there is no explanatory comment. Please either:
- Confirm this duplication serves a purpose and add a comment explaining why, or
- Remove the unnecessary call if it's unintentional.
configure (1)
3-3: Header update looks consistent.The generation stamp now aligns with the Autoconf 2.72 toolchain reflected elsewhere in the script.
config.sub (2)
946-968: x86 default vendor normalization OK; confirm impact on downstream.Using
pcvendor fori*86|x86_64improves consistency, but may differ from previous tuples in your build/tests. Please confirm no consumers rely on prior vendor strings.
1882-1883: Final echo format changed; ensure kernel inclusion logic matches callers.
echo "$cpu-$vendor-${kernel:+$kernel-}$os"omits the vendor when unknown only if explicitly set elsewhere. Verify scripts/tests expecting a 3- or 4-part tuple handle this${kernel:+...}usage.config.guess (1)
151-189: LIBC detection heuristics simplified; verify musl/uclibc paths.Given broader use of
unknownvendor, ensure downstream configure logic consumes*-unknown-linux-musland*-unknown-linux-gnu*tuples as before.src/plugin_pathtranslator.cpp (3)
53-71: Init/Restart OK; minor: free only when allocated.Allocates
tmpand frees; OK. Consider using a small stack buffer if values are bounded, but fine.Verify
RESTART_ENV_MAXSIZEvsMAX_ENV_VAR_SIZEconsistency; you may want to use the former.
126-150: Event hook wiring looks correct.INIT/RESTART/EXEC path handling and VIRTUAL_TO_REAL_PATH dispatch are consistent. After fixing translation logic, this should work as intended.
152-166: Plugin descriptor OK.Descriptor fields and factory function look fine.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (5)
src/plugin_pathtranslator.cpp (5)
77-81: Good fix: serialize by reference and init before use.Dereferencing
*pathMappingfor read/write and callingpathTranslator_Init()in both hooks resolves earlier pointer/initialization issues.Also applies to: 86-90
2-13: Fix headers: add C++ std headers, drop unused POSIX, dedupe include (build fails).
- Add: , <unordered_map>, .
- Remove unused/non‑portable: dirent.h, fcntl.h, stdarg.h, sys/time.h, sys/types.h, sys/stat.h, sys/vfs.h.
- Keep: <limits.h>, <stdio.h>, , .
- Remove duplicate
#include "util.h".-#include <dirent.h> -#include <fcntl.h> -#include <limits.h> // for PATH_MAX -#include <stdarg.h> -#include <stdio.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/vfs.h> -#include <cstring> -#include <cstdlib> +#include <limits.h> // for PATH_MAX +#include <stdio.h> +#include <cstring> +#include <cstdlib> +#include <string> +#include <unordered_map> +#include <sstream> @@ -#include "util.h" -#include "util.h" +#include "util.h"Clang error “‘dirent.h’ file not found” is resolved by removing it. Based on static analysis hints.
Also applies to: 18-19
26-27: Qualify std symbols (unordered_map, string, stringstream).Either fully qualify or add using-declarations inside the namespace to avoid compile errors.
namespace dmtcp { +using std::string; +using std::unordered_map; +using std::stringstream;
21-22: Fix mapping grammar and parser: type/correctness; last‑wins.
- Comment/example contradict code. Use semicolon‑delimited “old:new” pairs.
- Use size_type and JASSERT; remove non‑existent ASSERT_NE.
- Skip empty tokens; prefer last‑wins (
operator[]) overinsert.-// Semicolon delimited list of path mappings of the form -// "/path/a:/path/a_new:/path/b:/path/b_new:/path/b/c:/path/c_new" +// Semicolon-delimited list of path mappings in the form: +// "/path/a:/path/a_new;/path/b:/path/b_new;/path/b/c:/path/c_new" @@ - stringstream ss(pathMappingStr); // Create a stringstream from the string - string token; + stringstream ss(pathMappingStr); + string token; @@ - // Tokenize using ; as a delimiter - while (std::getline(ss, token, ';')) { - int colonIdx = token.find(':'); - ASSERT_NE(colonIdx, string::npos); - string path = token.substr(0, colonIdx); - string newPath = token.substr(colonIdx + 1); - JASSERT(!path.empty()); - JASSERT(!newPath.empty()); - pathMapping->insert(make_pair(path, newPath)); - } + // Expected format: "old1:new1;old2:new2;..." + while (std::getline(ss, token, ';')) { + if (token.empty()) continue; + std::string::size_type colonIdx = token.find(':'); + JASSERT(colonIdx != std::string::npos)(token).Text("Bad mapping; expect old:new"); + string path = token.substr(0, colonIdx); + string newPath = token.substr(colonIdx + 1); + JASSERT(!path.empty()); + JASSERT(!newPath.empty()); + (*pathMapping)[path] = newPath; // last-wins + }Also applies to: 39-51
114-123: Path translation should preserve suffix, use longest prefix, and enforce path boundary + NUL.Current code replaces the entire path and can pick a shorter/ambiguous match;
strncpymay omit NUL.- for (auto &mapping : *pathMapping) { - if (Util::strStartsWith(virtPath, mapping.first.c_str())) { - strncpy(data->virtualToRealPath.path, mapping.second.c_str(), PATH_MAX); - return; - } - } + const char* bestNew = nullptr; + size_t bestLen = 0; + for (const auto &kv : *pathMapping) { + const string &oldp = kv.first; + const string &newp = kv.second; + if (Util::strStartsWith(virtPath, oldp.c_str())) { + char next = virtPath[oldp.size()]; + if (oldp.size() > bestLen && (next == '/' || next == '\0')) { + bestLen = oldp.size(); + bestNew = newp.c_str(); + } + } + } + if (bestNew) { + const char* suffix = virtPath + bestLen; + int n = snprintf(data->virtualToRealPath.path, PATH_MAX, "%s%s", bestNew, suffix); + JASSERT(n > 0 && n < PATH_MAX).Text("Translated path exceeds PATH_MAX"); + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/plugin_pathtranslator.cpp(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/plugin_pathtranslator.cpp (1)
src/dmtcpplugin.cpp (2)
dmtcp_get_restart_env(331-410)dmtcp_get_restart_env(331-334)
🪛 Clang (14.0.6)
src/plugin_pathtranslator.cpp
[error] 2-2: 'dirent.h' file not found
(clang-diagnostic-error)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
adda781 to
eddd20f
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
config.sub (2)
980-983: Typo breaks OS default: Basic_os → basic_osVariable name case is wrong; default OS never applied for c90.*.
Apply this fix:
- basic_os=${Basic_os:-unicos} + basic_os=${basic_os:-unicos}
1052-1055: e500v[12] mapping likely incorrect (OS mutated with "spe")Appending "spe" to basic_os can yield nonstandard OS tokens (e.g., linux-gnuspe) that later validation doesn’t recognize. Upstream convention is to model SPE via CPU (powerpcspe), not OS.
- e500v[12]-*) - cpu=powerpc - basic_os=${basic_os}"spe" - ;; + e500v[12]-*) + cpu=powerpcspe + # leave basic_os unchanged + ;;
♻️ Duplicate comments (2)
src/plugin_pathtranslator.cpp (2)
40-70: Missing namespace qualifiers will cause compilation errors.Inside the
dmtcpnamespace, unqualified uses ofstring,stringstream, andunordered_map(lines 42, 54, 55, 64, 65, etc.) will not resolve unless you addusingdeclarations orstd::prefixes consistently.Add at the top of the namespace:
namespace dmtcp { + +using std::string; +using std::unordered_map; +using std::stringstream; static unordered_map<string, string> *pathMapping = nullptr;Or qualify all uses with
std::.
137-149: Path translation lacks longest-prefix matching and doesn't stop after match.The current implementation has two critical flaws:
Non-deterministic results:
unordered_mapiteration order is undefined. If mappings overlap (e.g.,/varand/var/log), whichever is encountered first will be applied, not the longest match.No early exit: After translating a path (line 145), the loop continues. If another prefix matches the already-translated path, it could be transformed again, corrupting the result.
Replace with longest-prefix logic:
- for (const auto &mapping : *pathMapping) { - const string &oldp = mapping.first; - const string &newp = mapping.second; - if (Util::strStartsWith(virtPath, oldp.c_str())) { - // boundary check: next char must be '/' or end - char next = virtPath[oldp.size()]; - if (next == '/' || next == '\0') { - const char* suffix = virtPath + oldp.size(); - int n = snprintf(data->virtualToRealPath.path, PATH_MAX, "%s%s", newp.c_str(), suffix); - JASSERT(n > 0 && n < PATH_MAX).Text("Translated path exceeds PATH_MAX"); - } - } - } + const string *bestOldPath = nullptr; + const string *bestNewPath = nullptr; + size_t bestLen = 0; + + for (const auto &mapping : *pathMapping) { + const string &oldp = mapping.first; + const string &newp = mapping.second; + if (Util::strStartsWith(virtPath, oldp.c_str())) { + char next = virtPath[oldp.size()]; + if ((next == '/' || next == '\0') && oldp.size() > bestLen) { + bestLen = oldp.size(); + bestOldPath = &oldp; + bestNewPath = &newp; + } + } + } + + if (bestNewPath) { + const char* suffix = virtPath + bestLen; + int n = snprintf(data->virtualToRealPath.path, PATH_MAX, "%s%s", bestNewPath->c_str(), suffix); + JASSERT(n > 0 && n < PATH_MAX).Text("Translated path exceeds PATH_MAX"); + }
🧹 Nitpick comments (1)
config.sub (1)
1309-1311: Quote variable in test to avoid word-splitting/globbingHarmless in most cases, but safer and standard.
-if test x$basic_os != x +if test x"$basic_os" != x
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
config.guess(28 hunks)config.sub(21 hunks)configure(3 hunks)plugin/Makefile.am(0 hunks)plugin/Makefile.in(1 hunks)plugin/pathvirt/pathvirt.cpp(0 hunks)plugin/pathvirt/pathvirt.h(0 hunks)src/Makefile.am(1 hunks)src/Makefile.in(6 hunks)src/plugin/ipc/file/fileconnection.cpp(1 hunks)src/plugin_pathtranslator.cpp(1 hunks)src/pluginmanager.cpp(2 hunks)
💤 Files with no reviewable changes (3)
- plugin/pathvirt/pathvirt.h
- plugin/Makefile.am
- plugin/pathvirt/pathvirt.cpp
🚧 Files skipped from review as they are similar to previous changes (5)
- src/plugin/ipc/file/fileconnection.cpp
- src/pluginmanager.cpp
- src/Makefile.in
- src/Makefile.am
- configure
🧰 Additional context used
🪛 Clang (14.0.6)
src/plugin_pathtranslator.cpp
[error] 22-22: 'limits.h' file not found
(clang-diagnostic-error)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (10)
plugin/Makefile.in (1)
186-188: LGTM: Pathvirt dependency tracking correctly removed.The removal of
pathvirt/$(DEPDIR)/pathvirt.Pofromam__depfiles_remadeis consistent with the elimination of the Pathvirt plugin. Since this is an auto-generated file (from Makefile.am), the changes reflect the source modifications correctly.src/plugin_pathtranslator.cpp (4)
42-44: Proper alignment implemented for placement-new.The use of
alignas(unordered_map<string, string>)correctly addresses the alignment requirement for placement-new construction. This prevents undefined behavior from misaligned storage.
92-108: Serialization correctly dereferences pathMapping.Both
PrepareForExecandPostExecproperly dereferencepathMappingwhen serializing (*pathMappingon lines 98 and 107), and both callpathTranslator_Init()for null-safety.
152-179: Event hook dispatcher is well-structured.The
pathTranslator_EventHookproperly dispatches to specialized handlers for each event type. The switch-case pattern is appropriate for plugin event handling.
181-195: Plugin descriptor follows DMTCP conventions.The plugin descriptor and accessor function conform to DMTCP's plugin API, providing proper version information and event hook registration.
config.guess (3)
3-8: I need to check what's at lines 62-70 to understand the full scope of the concern:Let me check what's on lines 62-70 and see if config.sub also exists:
Based on the verification, I now have clear evidence. Let me check lines 62-70 and config.sub:
Sync config.guess to recent upstream version
The upstream config.guess at Savannah GNU has timestamp='2024-07-27' with copyright 1992-2024, while the vendored version is dated 2022-01-09 with copyright 1992-2022. The upstream script implements age checking that warns if the script is less than 3 years old. The current version is ~2.5 years behind. Although modern architectures including loongarch, riscv64be, and aarch64 are already present in the current file, keeping config.guess in sync with upstream follows GNU build system best practices and ensures platform detection remains current as new architectures emerge.
270-306: Verified: No vendor-based packaging logic foundThe search revealed no vendor-based conditionals in the configure script or Makefiles. Vendor variables exist only as substitutions (@build_vendor@, @host_vendor@), not as decision points. The
vendor=pcpattern is specific to x86/PC architectures and does not apply to BSD systems. The change tovendor=unknownfor these BSD systems is a safe standardization with no impact on packaging logic.
1153-1164: No issues found; triplets are properly validated by config.subThe code change correctly generates
x86_64-pc-linux-gnux32(ormuslx32) triplets via the__ILP32__probe, and config.sub's kernel-os validation explicitly accepts these via wildcard patterns (linux-gnu*,linux-musl*at lines 1774-1775). No downstream code relying on older vendor strings was found in the codebase.config.sub (2)
1882-1883: Verification complete: No problematic triplet parsing foundSearched the codebase for naive three-field splitting patterns and config.sub usage. Found that config.sub output is consumed by the standard GNU autotools configure script, which captures the triplet into shell variables (
ac_cv_build,ac_cv_host) without manually parsing or splitting on field count. No custom triplet parsing logic exists in shell, C, or C++ code that would break with an optional kernel segment. The optional kernel format is compatible with this codebase's autotools integration.
3-8: Remove misleading regression claim; acknowledge 2.5-year gap with real architectural enhancementsThe downgrade to 2022 scripts is factual (current upstream is at 2024-07-27 with 2025 updates), but the specific "regressions" suggested don't materialize: loongarch and riscv64be already exist in the 2022-01 versions. However, newer upstream versions do include genuine platform improvements (ARM64EC, aarch64c variants, and enhanced Android detection) added during 2023–2024. If target platforms require these newer architectures, syncing to recent upstream is advisable.
| cpu=i586 | ||
| ;; | ||
| pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*) | ||
| pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) | ||
| cpu=i686 | ||
| ;; |
There was a problem hiding this comment.
CPU alias typo: 'athalon_' should be 'athlon_'
This prevents normalization for common Athlon patterns.
- pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
+ pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| cpu=i586 | |
| ;; | |
| pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*) | |
| pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) | |
| cpu=i686 | |
| ;; | |
| cpu=i586 | |
| ;; | |
| pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*) | |
| cpu=i686 | |
| ;; |
🤖 Prompt for AI Agents
In config.sub around lines 1076 to 1080, the CPU alias pattern contains a typo:
"athalon_*" should be "athlon_*"; update the case pattern to replace "athalon_*"
with "athlon_*" so Athlon CPU names normalize correctly (ensure the pattern
remains a valid shell case alternative and retains surrounding separators and
whitespace).
|
I'll review it more carefully later. |
eddd20f to
0d7db9c
Compare
Sorry for taking this long to fix this. Apparently, DMTCP doesn't work on newer Ubuntu with Apple M3 chips so I had to revert to an older ubuntu. I manually removed the autoconf changes. It should be ready for a review now. |
0d7db9c to
f126ee1
Compare
f126ee1 to
43c96d1
Compare
Summary by CodeRabbit
Release Notes
New Features
Removed Features
Chores