I'm currently writing a http server, that has to run over all files inside a folder. One Request can write a file, where another Request can read the files at the same time, so i need to lock the file, that is open for writing. In the Routine, that will read the file, i just want to skip the file that is locked. To make this, i want to use locklibrarys like that from rubyist or nightlyone.
The problem is, i didnt get them to work, so i started to call the syscall.FcntlFlock() function myself and it didn't work like i had expected.
This program doesn't work in the Go Playground, cause the playground seems to run not on a unix-based system (syscall.FcntlFlock is undefined)
The code that didn't work:
func main() {
time.Sleep(time.Second)
file, err := os.Open("lockfiletest.lock")
if err != nil {
log.Printf("error opening file2: %s", err)
return
}
defer file.Close()
flockT := syscall.Flock_t{
Type: syscall.F_WRLCK,
Whence: io.SeekStart,
Start: 0,
Len: 0,
}
err = syscall.FcntlFlock(file.Fd(), syscall.F_SETLK, &flockT)
if err != nil {
log.Printf("error locking file2: %s", err)
return
}
log.Println("lock2 accessed")
time.Sleep(time.Second * 5)
log.Println("func2 finished")
time.Sleep(time.Second * 15)
}
the console output:
2017/10/28 00:18:12 error locking file2: bad file descriptor
Process finished with exit code 0
What am i doing wrong? Are the syscalls broken?
I also tried it in C and there it works fine.
I test this program in Go1.8.3 and Go1.9.1 on ubuntu16.04
PS: This program also have to run on windows, so only implementing a FcntlLock isn't enough.
I also thoght about using sync.RWMutex, so it is locked via a Mutex instead of a fileLock. That is not exactly what i want, cause i only want to skip the file that is locked and not wait until the mutex can be locked.