Search code examples
clinuxmemorysystem-calls

Can madvise(addr, size, MADV_DONTNEED) cause segfaults?


Is madvise(*, *, MADV_DONTNEED) supposed to be purely advisory? I tried scanning /proc/self/maps and calling madvise(addr, size, MADV_DONTNEED) on the entries:

#include <stdio.h>
#include <sys/mman.h>

int main(void) {
    FILE *fp;
    char line[1024];

    fp = fopen("/proc/self/maps", "r");
    if (fp == NULL) {
        perror("Failed to open maps file");
        return 1;
    }

    while (fgets(line, sizeof(line), fp)) {
        char addr[32], perms[8], offset[32], dev[32], inode[32], path[256];
        unsigned long start, end;

        path[0] = '\0';
        sscanf(line, "%lx-%lx %s %s %s %s %[^\n]", &start, &end, perms, offset, dev, inode, path);

        int ret = madvise((void*)start, end - start, MADV_DONTNEED);
        if(ret == 0)
            printf("  OK\n");
        else
            printf("  Error\n");
        fflush(stdout);
    }

    fclose(fp);
}

But this prints:

  OK
  OK
  OK
  OK
Segmentation fault

Is there a simple way to tell (from /proc/self/maps, /proc/self/smaps or otherwise) which memory segments a process is allowed to call madvise(*, *, MADV_DONTNEED) on?


Solution

  • man 2 madvise says:

    These advice values do not influence the semantics of the application (except in the case of MADV_DONTNEED), but may influence its performance.

    And:

    After a successful MADV_DONTNEED operation, the semantics of memory access in the specified region are changed: subsequent accesses of pages in the range will succeed, but will result in either repopulating the memory contents from the up-to-date contents of the underlying mapped file (for shared file mappings, shared anonymous mappings, and shmem-based techniques such as System V shared memory segments) or zero-fill-on-demand pages for anonymous private mappings.

    And man 3 posix_madvise says:

    the corresponding madvise(2) value, MADV_DONTNEED, has destructive semantics.

    So no, it's not purely advisory, and yes, it can cause segfaults if you blindly do it everywhere.