Skip to content

Instantly share code, notes, and snippets.

@ramielrowe
Created July 16, 2019 16:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ramielrowe/cf41891d38fa9bf636b7f45eb81a0cd0 to your computer and use it in GitHub Desktop.
Save ramielrowe/cf41891d38fa9bf636b7f45eb81a0cd0 to your computer and use it in GitHub Desktop.
azure_mmap_segfault
package main
import (
"context"
"errors"
"fmt"
"os"
"syscall"
"time"
"golang.org/x/sync/errgroup"
)
func fatal(msg string) {
fmt.Println(msg)
os.Exit(1)
}
type mmf []byte
func newMMF(file *os.File, writable bool, offset int64, length int) (mmf, error) {
prot, flags := syscall.PROT_READ, syscall.MAP_SHARED // Assume read-only
if writable {
prot, flags = syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED
}
addr, err := syscall.Mmap(int(file.Fd()), offset, length, prot, flags)
return mmf(addr), err
}
func (m *mmf) unmap() {
err := syscall.Munmap(*m)
*m = nil
if err != nil {
fatal("if we are unable to unmap the memory-mapped file, there is serious concern for memory corruption")
}
}
func read(ctx context.Context, m []byte, i int) error {
time.Sleep(time.Second)
select {
case <-ctx.Done():
return ctx.Err()
default:
b := m[i]
if b == byte('e') {
return errors.New("Some Error")
}
}
return nil
}
func run() error {
ctx := context.Background()
group, gCtx := errgroup.WithContext(ctx)
f, err := os.Open("test.txt")
if err != nil {
fatal(err.Error())
}
s, err := f.Stat()
if err != nil {
fatal(err.Error())
}
m, err := newMMF(f, false, 0, int(s.Size()))
if err != nil {
fatal(err.Error())
}
defer m.unmap()
work := make(chan int, 5)
for c := 0; c < 5; c++ {
group.Go(func() error {
for w := range work {
err := read(gCtx, m, w)
if err != nil {
return err
}
}
return nil
})
}
for i := 0; i < len(m); i++ {
work <- i
}
close(work)
return group.Wait()
}
func main() {
run()
time.Sleep(10 * time.Second)
}
package main
import (
"context"
"errors"
"fmt"
"os"
"syscall"
"time"
)
func fatal(msg string) {
fmt.Println(msg)
os.Exit(1)
}
type mmf []byte
func newMMF(file *os.File, writable bool, offset int64, length int) (mmf, error) {
prot, flags := syscall.PROT_READ, syscall.MAP_SHARED // Assume read-only
if writable {
prot, flags = syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED
}
addr, err := syscall.Mmap(int(file.Fd()), offset, length, prot, flags)
return mmf(addr), err
}
func (m *mmf) unmap() {
err := syscall.Munmap(*m)
*m = nil
if err != nil {
fatal("if we are unable to unmap the memory-mapped file, there is serious concern for memory corruption")
}
}
func read(m []byte, i int) error {
time.Sleep(time.Second)
b := m[i]
if b == byte('e') {
return errors.New("Some Erroor")
}
return nil
}
func run() error {
ctxOutter := context.Background()
_, cancel := context.WithCancel(ctxOutter)
defer cancel()
f, err := os.Open("test.txt")
if err != nil {
fatal(err.Error())
}
s, err := f.Stat()
if err != nil {
fatal(err.Error())
}
m, err := newMMF(f, false, 0, int(s.Size()))
if err != nil {
fatal(err.Error())
}
defer m.unmap()
work := make(chan int, 5)
resultChan := make(chan error, len(m))
for g := 0; g < 5; g++ {
go func() {
for w := range work {
resultChan <- read(m, w)
}
}()
}
for i := 0; i < len(m); i++ {
work <- i
}
close(work)
for result := range resultChan {
if result != nil {
return result
}
}
return nil
}
func main() {
run()
time.Sleep(10 * time.Second)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment