This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
The following commit(s) were added to refs/heads/master by this push:
new 642720e9b examples/configdata: exercise unregister/register lifetime
642720e9b is described below
commit 642720e9b4bfd885b0f11814812df120ef7edefd
Author: Arnav Sharma <[email protected]>
AuthorDate: Wed Sep 16 23:12:10 2026 +0530
examples/configdata: exercise unregister/register lifetime
Add a regression test for apache/nuttx#20166 to the configdata
example, which runs automatically in every sim:configdata build.
After the normal configdata test loops, close the long-lived
descriptor and run a full lifetime cycle on /dev/config:
- mtdconfig_unregister() must succeed,
- the unregistered device must no longer be openable (ENOENT),
- the same MTD device must be registerable again and usable,
- a final unregister must succeed, leaving the device unregistered.
Before the driver fix this crashes deterministically: the old
mtdconfig_unregister_by_path() freed the private device structure
before closing its temporary file, so the subsequent open() faults
in mm_malloc on the corrupted heap (SIGSEGV observed on sim right
after unregister returns). With the fix the whole example,
934706/934706 checks included, completes cleanly.
The test uses only generic configdata APIs, so it also passes
unchanged under CONFIG_MTD_CONFIG_NVS, whose open/close callbacks
are no-ops.
Assisted-by: Claude:claude-opus
Signed-off-by: Arnav Sharma <[email protected]>
---
examples/configdata/configdata_main.c | 85 +++++++++++++++++++++++++++++++++--
1 file changed, 81 insertions(+), 4 deletions(-)
diff --git a/examples/configdata/configdata_main.c
b/examples/configdata/configdata_main.c
index 007a9d162..616c936f9 100644
--- a/examples/configdata/configdata_main.c
+++ b/examples/configdata/configdata_main.c
@@ -342,11 +342,11 @@ static int configdata_fillconfig(void)
}
#if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0
- printf(" Created entry %04X, %d Len=%d\n",
- entry->id, entry->instance, entry->len);
+ printf(" Created entry %04X, %d Len=%d\n",
+ entry->id, entry->instance, entry->len);
#endif
- g_nentries++;
- g_ntotalalloc++;
+ g_nentries++;
+ g_ntotalalloc++;
}
}
@@ -477,6 +477,7 @@ static int configdata_delentries(void)
/* Are there any files to be deleted? */
int nentries = g_nentries - g_ndeleted;
+
if (nentries < 1)
{
return 0;
@@ -609,6 +610,80 @@ static void configdata_cleardeleted(void)
g_ndeleted = 0;
}
+/****************************************************************************
+ * Name: configdata_testunregister
+ *
+ * Description:
+ * Exercise the /dev/config register/unregister lifetime. Unregister
+ * the device, verify that it can no longer be opened, then register
+ * it again and verify that it is usable. This is a regression test:
+ * freeing the private device structure before the temporary file used
+ * during unregister is closed corrupts the heap and crashes the open
+ * below.
+ *
+ * Input Parameters:
+ * mtd - Pointer to the MTD device bound to the /dev/config device
+ *
+ ****************************************************************************/
+
+static void configdata_testunregister(FAR struct mtd_dev_s *mtd)
+{
+ int fd;
+ int ret;
+
+ close(g_fd);
+ g_fd = -1;
+
+ ret = mtdconfig_unregister();
+ if (ret < 0)
+ {
+ printf("ERROR: /dev/config unregistration failed: %d\n", ret);
+ fflush(stdout);
+ exit(3);
+ }
+
+ fd = open("/dev/config", O_RDONLY);
+ if (fd >= 0 || errno != ENOENT)
+ {
+ printf("ERROR: /dev/config still accessible after unregister: "
+ "fd=%d errno=%d\n", fd, errno);
+ fflush(stdout);
+
+ if (fd >= 0)
+ {
+ close(fd);
+ }
+
+ exit(3);
+ }
+
+ ret = mtdconfig_register(mtd);
+ if (ret < 0)
+ {
+ printf("ERROR: /dev/config re-registration failed: %d\n", ret);
+ fflush(stdout);
+ exit(3);
+ }
+
+ fd = open("/dev/config", O_RDONLY);
+ if (fd < 0)
+ {
+ printf("ERROR: Failed to re-open /dev/config %d\n", errno);
+ fflush(stdout);
+ exit(3);
+ }
+
+ close(fd);
+
+ ret = mtdconfig_unregister();
+ if (ret < 0)
+ {
+ printf("ERROR: /dev/config final unregistration failed: %d\n", ret);
+ fflush(stdout);
+ exit(3);
+ }
+}
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -786,6 +861,8 @@ int main(int argc, FAR char *argv[])
configdata_delallfiles();
#endif
+ configdata_testunregister(mtd);
+
configdata_endmemusage();
fflush(stdout);
return 0;