A problem with fork() and subsequent flock()

Manish Jain unxfbsdi at gmail.com
Fri Nov 7 16:16:58 PST 2008


Hi,

I am starting out as a C/C++ programmer on FreeBSD and I am stuck with a 
small but irritating problem. I was trying out the flock() call and 
wrote flocksample.cpp, which starts out with a fork() and subsequent 
calls to flock() from both processes (parent as well as child; the child 
does an initial sleep(1) before anything else). It compiles okay and the 
parent's  flock() call succeeds. But the child's flock() call too 
succeeds on the same file descriptor even before the first flock() 
unlocks. Can anyone please point out where the problem is ? I am not 
even sure whether the problem is FreeBSD specific.

Attached is flocksample.cpp

Thanks for any help
Manish Jain
unxfbsdi at gmail.com

-------------- next part --------------
#include <sys/stat.h>
#include <sys/file.h>
#include <unistd.h>
#include <cstdio>

#include <cstring>
#include <iostream>
#include <cassert>
using namespace std;

const char * szFileName = "/tmp/flock.log";
int addfunc(int fd);
int readfunc(int fd);

int main()
{
	int fd = open(szFileName, O_RDWR | O_CREAT);
	assert(fd > 2);
	
	if (fork())
	{
		return addfunc(fd);
	}
	else
	{
		cout << "Child sleeping for 1s before attempting to read log" << endl;
		sleep(1); //ensure that child's readfunc starts after parent's addfunc
		return readfunc(fd);
	}
}

int addfunc(int fd)
{
	char buffer[4];
	int i = 0;

	int result = flock(fd, LOCK_EX);
	assert(result == 0);

	while(i < 10)
	{
		sprintf(buffer, "%d\n\0", ++i);
		write(fd, buffer, strlen(buffer));
	}
	
	while(*buffer != 'U')
	{
		cout << "Blocking on addfunc. Type U to unlock log" << endl;
		cin >> buffer;
	}
	
	cout << "Unblocking on addfunc ..." << endl;
	close(fd); //automatically calls LOCK_UN
	return 0;
}

int readfunc(int fd)
{
	struct stat fstat;

	int result = flock(fd, LOCK_SH);
	assert(result == 0);

	cout << "readfunc got hold of log ..." << endl;
	lstat(szFileName, &fstat);
	char * buffer = new char[fstat.st_size + 1];
	lseek(fd, 0, SEEK_SET);
	
	while (result < fstat.st_size)
	{
		result += read(fd, buffer + result, (fstat.st_size - result));
	}
	
	close(fd); //automatically calls LOCK_UN
	buffer[result] = 0;
	
	cout << "Following are the contents of the file flock.log :" << endl;
	cout << buffer << endl;
	
	delete[] buffer;
	return 0;
}


More information about the freebsd-fs mailing list