Linux-api Archive mirror
 help / color / mirror / Atom feed
From: Levo D <l-asm@mail9fcb1a.bolinlang.com>
To: <linux-api@vger.kernel.org>
Subject: mmap causing bus error
Date: Wed,  8 Nov 2023 20:21:55 +0000	[thread overview]
Message-ID: <20231108202155.404E0FA16D@bolin> (raw)

[-- Attachment #1: Type: text/plain, Size: 703 bytes --]

When I mmap a file it's possible to have a bus error and I attached some code to reproduce it

The reproduce steps are in main.c. I choose to use mmap because I noticed doing an `read` on a large file is a bit slow. It seems like the kernel will zero out everything then write the file contents to the buffer. mmap is significantly faster but risk corrupting data and having a bus error (also doesn't seem like zero copy).

Essentially what the program is is write to the contents of the file while main.c is using it which causes bad data OR it will TRUNC the file and cause a bus error + coredump. Are there ways to get a copy without being as 'slow' as `read` and doesn't have the downsides of mmap?

[-- Attachment #2: main.c --]
[-- Type: application/octet-stream, Size: 1508 bytes --]

/* Reproducable steps
gcc -g main.c -o app1
gcc -g app2.c -o app2
fn=/tmp/uB2kCDFlDoRA56gdeuvOVKbL1KHXxMhDXc3pFnhjbhc
dd if=/dev/zero of=$fn count=5120 bs=4096; ./app1 $fn 1 | ./app2 $fn
You'll see "Result was 72" instead of "Result was 0"
(app 2 modifies $fn so we'll need dd again)
dd if=/dev/zero of=$fn count=5120 bs=4096; ./app1 $fn 0 | ./app2 $fn
You'll see the desired "Result was 0"
In app2.c uncomment/comment line 13 and 12
gcc app2.c -o app2
Now this will have a bus error and "Result" line will not print
dd if=/dev/zero of=$fn count=5120 bs=4096; ./app1 $fn 1 | ./app2 $fn
read is unaffected
dd if=/dev/zero of=$fn count=5120 bs=4096; ./app1 $fn 0 | ./app2 $fn
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
	//a.out filename 1
	if (argc != 3) {
		fprintf(stderr, "Bad args\n");
		return 1;
	}
	
	int fd = open(argv[1], O_RDONLY);
	struct stat s={0};
	fstat(fd, &s);
	char*p;
	if (argv[2][0] == '1')
		p = (char*)mmap(0, s.st_size, PROT_READ , MAP_PRIVATE, fd, 0);
	else {
		p = (char*)malloc(s.st_size);
		read(fd, p, s.st_size);
	}
	write(2, "Sleeping\n", 9);
	write(1, "Sleeping\n", 9); //Triggers the other app to write
	sleep(1);
	write(2, "Waking\n", 7);

	//read first byte of every 4k page
	int sum = 0;
	for (long i=0; i<s.st_size; i+=4096) {
		if (p[i] != 0) {
			int z=0;
		}
		sum += p[i];
	}
	fprintf(stderr, "Result was %d\n", sum);
	return 0;
}


[-- Attachment #3: app2.c --]
[-- Type: application/octet-stream, Size: 401 bytes --]

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
	if (argc != 2) {
		fprintf(stderr, "Bad args\n");
		return 1;
	}
	char buf[4096];
	read(0, buf, 4096);
	int fd = open(argv[1], O_WRONLY|O_CREAT);
	//int fd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC); //<-- This one causes a bus error
	write(fd, "Hello", 5);
	fprintf(stderr, "Written %d\n", fd);
}

                 reply	other threads:[~2023-11-08 20:21 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231108202155.404E0FA16D@bolin \
    --to=l-asm@mail9fcb1a.bolinlang.com \
    --cc=linux-api@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).