Members

Technology Zones

Articles

Hosted By

MaximumASP

Info

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

Last post 04-15-2008 1:26 PM by chong. 0 replies.
Page 1 of 1 (1 items)
Sort Posts: Previous Next
  • 04-15-2008 1:26 PM

    • chong
    • Not Ranked
    • Joined on 01-22-2008
    • United Kingdom
    • Junior Member
    • Points 110

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

    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
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    • Post Points: 5
Page 1 of 1 (1 items)