brain teaser: file sharing by an application and its child(s)

  • 12 years ago

    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|
      // an error to open the file. we have to terminate this session
      fprintf(stderr,"Fatal(parent):failed to open our database file %s",filename);
     } // 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
     } // if

     // Set the file pointer to the beginning of the file
     if (SetFilePointer(filehandle,(LONG)0,(PLONG)NULL,FILE_BEGIN)
      == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
      printf("Fatal(parent): SetFilePointer() failed\n");
     } // 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());
     } // 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) {
      printf("Fatal(parent): SetFilePointer() failed\n");
     } // if

     while (1) {
      if (ReadFile(filehandle,buf,len_of_record,&nbytes,NULL) == 0) {
       printf("Parent: error for ReadFile()=%d\n",err=GetLastError());
      } else if (nbytes == 0) {
       // end of file reached
      }// if & else if
      buf[len_of_record] = '\0';
     } // while


     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 ){
      printf("child: SetFilePointer() failed\n");
     } // 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
     } // if

     printf("End of the child\n");
    } // main

Post a reply

No one has replied yet! Why not be the first?

Sign in or Join us (it's free).


Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“In theory, theory and practice are the same. In practice, they're not.”