Hi guys,
I have got something to test your understanding of multitasking processes. Have a fun!!
An application opens a file and starts a child process passing the file handle to the child. The application(parent) and its child share the file. When these two processes write to or read the file, a big problem can occur if they do not snychronise their wirting and reading of the file!! Why?
Try the following example programs (testp.cpp & testc.cpp). Run testp.exe and observe the problem!!
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// testp.cpp : the parent application
//
// When running, this program prints the following to the screen:
// End of the child
// child*
// parent
// Parent: exiting
//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <process.h>
#include <windows.h> // for Sleep( )
#include <winbase.h> // for Sleep( )
//#include <winnt.h> // For SECURITY_ATTRIBUTES
#define len_of_record 6 // for length of a record in the file
#define filename "test.txt" // our database file
int main( )
{
char buf[100]; unsigned long nbytes;
HANDLE filehandle;
char filehandle_str[20];
int err;
SECURITY_ATTRIBUTES sa; // For CreateProcess( ) & CreateFile( )
// For the file handle to be inherited by a child
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE; // We want the file to be inherited by a child
// *** Open our database file ***
// Note the file attributes flag FILE_FLAG_WRITE_THROUGH|FILE_FLAG_RANDOM_ACCESS
// to avoid lazy flush when writing to the disk.
if ((filehandle=CreateFile(filename,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|
FILE_SHARE_WRITE,&sa,OPEN_ALWAYS,FILE_FLAG_WRITE_THROUGH|
FILE_FLAG_RANDOM_ACCESS,NULL)) ==
INVALID_HANDLE_VALUE ) {
// an error to open the file. we have to terminate this session
fprintf(stderr,"Fatal(parent):failed to open our database file %s",filename);
Sleep(5000);
exit(3);
} // if
// We could use either CreateProcess( ) or spwanlp( ) to
// start/create a child.
itoa((int)filehandle, filehandle_str, 10);
// Create the child using spawnlp( )
if (spawnlp(P_NOWAIT,"testc.exe","testc.exe",filehandle_str,NULL)==-1){
// Error: failed to create a child process
fprintf(stderr,"Fatal: failed with CreateProcess( )\n");
fprintf(stderr,"Parent exits\n");
Sleep(4000); // To keep the output window open for 4 secs
exit(1);
} // if
// Set the file pointer to the beginning of the file
if (SetFilePointer(filehandle,(LONG)0,(PLONG)NULL,FILE_BEGIN)
== 0xFFFFFFFF && GetLastError() != NO_ERROR) {
CloseHandle(filehandle);
printf("Fatal(parent): SetFilePointer() failed\n");
Sleep(10000);
exit(2);
} // if
Sleep(2000); // Give the child enough time to exit!
// Write "parent" into the beginning of the file!
strcpy(buf,"parent"); //note strlen(buf) = len_of_record!
if (WriteFile(filehandle,buf,len_of_record,&nbytes,NULL) == 0 ||
nbytes != len_of_record) {
printf("Parent: error for WriteFile()=%d\n",err=GetLastError());
CloseHandle(filehandle);
Sleep(5000);
exit(4);
} // if
// *** We now read the records from the file ***
// Read the records from the file & print them to the screen
// Note that the position # of the 1st byte in a file is 0(zero), not 1.
if (SetFilePointer(filehandle,(LONG)0,(PLONG)NULL,FILE_BEGIN)
== 0xFFFFFFFF && GetLastError() != NO_ERROR) {
CloseHandle(filehandle);
printf("Fatal(parent): SetFilePointer() failed\n");
Sleep(10000);
exit(2);
} // if
while (1) {
if (ReadFile(filehandle,buf,len_of_record,&nbytes,NULL) == 0) {
printf("Parent: error for ReadFile()=%d\n",err=GetLastError());
CloseHandle(filehandle);
Sleep(5000);
exit(4);
} else if (nbytes == 0) {
// end of file reached
break;
}// if & else if
buf[len_of_record] = '\0';
printf("%s\n",buf);
} // while
_flushall();
CloseHandle(filehandle); // This does not affect the file open for the child
printf("Parent: exiting\n");
Sleep(20000); // Sleep for 20 seconds
} // main
// testc.cpp :the child application
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include <windows.h> // For Sleep( )
#include <winbase.h> // For Sleep( )
#define len_of_record 6 // a record is 6 chars long
#define filename "test.txt" // our database file
int main(int argc, char **argv)
{
char buf[len_of_record+1]; // buf to write to the file
unsigned long nbytes; // # of bytes written to or read from the file
HANDLE filehandle; // for our database file (opened for the parent too)
filehandle = (HANDLE) atoi(argv[1]); // file handle inherited from the parent
// write "child*" to the beginning of the file
strcpy(buf,"child*"); // note strlen(buf) = 6!
if (SetFilePointer(filehandle,0,(PLONG)0,FILE_BEGIN)==0xFFFFFFFF ){
CloseHandle(filehandle);
printf("child: SetFilePointer() failed\n");
Sleep(5000);
exit(2);
} // if
if (WriteFile(filehandle,buf,len_of_record,&nbytes,NULL)==0){
printf("child: WriteFile() failed\n");
printf(" error = %d\n",GetLastError()); //c.f. ERROR_LOCK_VIOLATION=33
CloseHandle(filehandle);
Sleep(20000);
exit(4);
} // if
printf("End of the child\n");
CloseHandle(filehandle);
} // main
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
No one has replied yet! Why not be the first?
Sign in or Join us (it's free).