Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[signal SIGBUS: bus error code=0x2 addr=0x1e4001 pc=0x2535] #12

Open
AllenRay opened this issue Sep 25, 2016 · 7 comments
Open

[signal SIGBUS: bus error code=0x2 addr=0x1e4001 pc=0x2535] #12

AllenRay opened this issue Sep 25, 2016 · 7 comments

Comments

@AllenRay
Copy link

go version
1.7.1
os
macos sierra

when i use mmap-go to write bytes to file occur error. the stack as below

unexpected fault address 0x1e4001
fatal error: fault
[signal SIGBUS: bus error code=0x2 addr=0x1e4001 pc=0x2535]

goroutine 1 [running]:
runtime.throw(0xb37ee, 0x5)
/usr/local/go/src/runtime/panic.go:566 +0x95 fp=0xc420035da0 sp=0xc420035d80
runtime.sigpanic()
/usr/local/go/src/runtime/sigpanic_unix.go:21 +0x1d0 fp=0xc420035df8 sp=0xc420035da0
main.main()
/Users/leizhenyu/work/src/github.com/GoRocketMQ/start/main-1.go:58 +0x4f5 fp=0xc420035f48 sp=0xc420035df8
runtime.main()
/usr/local/go/src/runtime/proc.go:183 +0x1f4 fp=0xc420035fa0 sp=0xc420035f48
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2086 +0x1 fp=0xc420035fa8 sp=0xc420035fa0
exit status 2

the line 58 code as below

mmaped[0] = 'x'

@mrka124
Copy link

mrka124 commented Apr 18, 2018

me too :(

@jcmiao
Copy link

jcmiao commented Aug 8, 2018

the same problem

@edsrzf
Copy link
Owner

edsrzf commented Dec 15, 2018

A minimal reproduction case would be helpful here.

@dspasibenko
Copy link

dspasibenko commented Apr 25, 2019

@edsrzf I hit the same problem on macos. This reproduced when provided mapped size is bigger than actual file size. So, in my case the code, called for a file f which size is 0:

mf, err := mmap.MapRegion(f, 12345*4096, mmap.RDWR, 0, 0)
...

doesn't change the file f size, so it remained 0. Seems like macos doesn't extend the file with the mapping. Can be easily fixed by f.Truncate(12345*4096) for the example above. Please consider.

@holiman
Copy link

holiman commented Oct 22, 2021

I've also been investigating this, and made a repro for it. I can repro it on both fedora and ubuntu. However, IIUC, it's not actually an issue with mmap per se, rather a filesystem thing.

See https://gist.github.com/holiman/ce51945058d2befaf718de3804fb9352 .

What that gist does, is that it creates a file, in the os temp folder, of 10Gb. On my fedora, the temp partition only holds 1Gb. Yet, the file creation completes without any problems.

If I check the file, du will tell me it's a few K bytes, and ls will tell me it's 10Gb. See https://unix.stackexchange.com/a/436318 for more info:

ls -l will give you the apparent size of the file, which is the number of bytes a program would read if it read the file from start to finish. du would give you the size of the file "on disk".

So what we've got is a 'sparse' file. And even though it's possible to read 10Gb from it, the underlying disk resource is way smaller. And the problem is that if I later try to fill it with data, at some point the underlying disk resource will grow larger than what the disk can hold ( in my case 1Gb), and there will be an error.

Back to mmap: in our use of mmap-go, we create a large file, truncate to size, close, and then do an mmap on it -- erroneously believing that we can use the full size of the mmap data, as it's already backed by the filesystem. Later on, as we're just filling the bytes, the same thing will happen though, and unexpected fault address is surfaced.

I'm not sure how this can be avoided. One (boring) solution could be to actually fill the file with data, write junk to it before mmap, to ensure that the disk actually will be able to store the data.

@holiman
Copy link

holiman commented Oct 22, 2021

For memory maps where the caller intends to write to the region, a check like this can be used to ensure that the required size is actually addressable:

	handle := int(dump.Fd())
	if err := syscall.Fallocate(handle, 0, 0, int64(fSize)); err != nil {
		return fmt.Errorf("Fallocate failed: %v", err)
	}

More info: https://unix.stackexchange.com/a/292849

It's obviously unix-specific.

@dchapes
Copy link
Contributor

dchapes commented Oct 23, 2021

It's obviously unix-specific.

It's linux specific¹. Other unix variants do not have fallocate. As with all use of package syscall, the Go source file importing it should have an appropriate go:build (or +build) build constraint. In this case //go:build linux and/or // +build linux with an alternative //go:build freebsd || netbsd || openbsd || dragonfly (etc) file that uses CGO to call C.posix_fallocate (unfortunately neither syscall nor golang.org/x/sys/unix provide a non-linux version of this functionality because it's in libc and not a syscall for other systems).

¹ The first paragraph of the fallocate(1) man page says:

This is a nonportable, Linux-specific system call. For the
portable, POSIX.1-specified method of ensuring that space is
allocated for a file, see posix_fallocate(3).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants