user3535936
user3535936

Reputation: 126

syncro multiprocess with FileLock() read/write on same file c++ win32

i'm traing to do 2 process that do this:

Process A (the client) : - It opens a temporary file for writing (use GetTempFileName to obtain a unique file name). - It starts Process B passing as argument the name of the file. - It reads from standard input strings of characters, and it writes those strings on the intermediate file. Use string of constant length (e.g., #define MAX_LEN 100). - It stops reading strings from standard input when it receives an end-of-file (ctrl-Z). - Before terminating, it writes the string ".end" as last line of the file.

Process B (the server) works as follows: - It opens the intermediate file for reading. - It reads lines as soon as they are available, and it prints them out on standard output.

but seams that the ReadFile on process B do not wait until the fileLock is removed so it terminate befor the first line is inserted

process A:

#include <windows.h>
#include <process.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <io.h>

#define MAX_LEN 100



int _tmain(int argc, LPTSTR argv[]){


    TCHAR tmpFileName[MAX_PATH];
    TCHAR tmppath[MAX_PATH];
    TCHAR moment[MAX_PATH];
    TCHAR command[MAX_PATH + 256];
    UINT uRetVal = 0;
    HANDLE bufferW,next;
    DWORD n;
    PROCESS_INFORMATION piS;
    STARTUPINFO siS;
    TCHAR buffer[MAX_LEN];
    int i=0;


    OVERLAPPED ov = { 0, 0, 0, 0, NULL };
    LARGE_INTEGER FilePos;


    ZeroMemory(&siS, sizeof(siS));
    siS.cb = sizeof(siS);
    ZeroMemory(&piS, sizeof(piS));





    uRetVal = GetTempFileName(_T("."), // directory for tmp files
        _T(""),     // temp file name prefix 
        0,                // create unique name 
        tmpFileName);  // buffer for name 

    if (uRetVal == 0)
    {
        _tprintf("\n errore apertura temp file");
        return (3);
    }


    GetCurrentDirectory(MAX_PATH, moment);
    //_stprintf(tmppath, "%s\\ %s",moment,tmpFileName);
    _tprintf("\n CLIENT PATH %s  \n",moment);



    //_stprintf(command,"%s %s","C:\\Users\\zio gianni\\Documents\\Visual Studio 2013\\Projects\\lab11server\\Debug\\lab11server.exe",tmpFileName);
    _stprintf(command, "%s %s", "server.exe", tmpFileName);
    bufferW = CreateFile(tmpFileName, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    next = CreateFile(tmpFileName, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (next == INVALID_HANDLE_VALUE) {

        _tprintf(_T("Cannot open client file. Error: %x\n"),
            GetLastError());
        _tprintf(" \n Nome File: %s\n", "./prova.bin");
        return 2;
    }
    if (bufferW == INVALID_HANDLE_VALUE) {

        _tprintf(_T("Cannot open client file. Error: %x\n"),
            GetLastError());
        _tprintf(" \n Nome File: %s\n", "./prova.bin");
        return 2;
    }


    FilePos.QuadPart = i*MAX_LEN * sizeof (TCHAR);
    ov.Offset = FilePos.LowPart;
    ov.OffsetHigh = FilePos.HighPart;
    ov.hEvent = 0;


    LockFileEx(bufferW, LOCKFILE_EXCLUSIVE_LOCK, 0, FilePos.LowPart, FilePos.HighPart, &ov);
    printf("file bloccato avvio server con comand: %s\n", command);



    if (!CreateProcess(NULL,   // No module name (use command line)
        command,        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        TRUE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &siS,            // Pointer to STARTUPINFO structure
        &piS)           // Pointer to PROCESS_INFORMATION structure
        )
    {
        printf("CreateProcess failed (%d).\n", GetLastError());
        return -5;
    }


    while (TRUE){



        scanf("%s",buffer);
        if (strcmp(buffer, "EOF")==0){

            break;
        }

        WriteFile(bufferW, buffer, MAX_LEN*sizeof(TCHAR), &n, NULL);


        FilePos.QuadPart =(i+1)* MAX_LEN * sizeof (TCHAR);
        ov.Offset = FilePos.LowPart;
        ov.OffsetHigh = FilePos.HighPart;
        ov.hEvent = 0;

        if (i % 2 == 0){

            LockFile(next, LOCKFILE_EXCLUSIVE_LOCK, 0, FilePos.LowPart, FilePos.HighPart, &ov);
            FilePos.QuadPart = (i )* MAX_LEN * sizeof (TCHAR);
            ov.Offset = FilePos.LowPart;
            ov.OffsetHigh = FilePos.HighPart;
            ov.hEvent = 0;
            UnlockFile(bufferW, 0, 0, 0, &ov);
        }
        else{

            LockFile(bufferW, LOCKFILE_EXCLUSIVE_LOCK, 0, FilePos.LowPart, FilePos.HighPart, &ov);
            FilePos.QuadPart = (i )* MAX_LEN * sizeof (TCHAR);
            ov.Offset = FilePos.LowPart;
            ov.OffsetHigh = FilePos.HighPart;
            ov.hEvent = 0;
            UnlockFile(next, 0, 0, 0, &ov);
        }

        i++;
    }



    sprintf(buffer, ".end");

    WriteFile(bufferW, buffer, MAX_LEN*sizeof(TCHAR), &n ,NULL);


if (i % 2 == 0){


        FilePos.QuadPart = (i)* MAX_LEN * sizeof (TCHAR);
        ov.Offset = FilePos.LowPart;
        ov.OffsetHigh = FilePos.HighPart;
        ov.hEvent = 0;
        UnlockFile(bufferW, 0, FilePos.LowPart, FilePos.HighPart, &ov);
    }
    else{


        FilePos.QuadPart = (i)* MAX_LEN * sizeof (TCHAR);
        ov.Offset = FilePos.LowPart;
        ov.OffsetHigh = FilePos.HighPart;
        ov.hEvent = 0;
        UnlockFile(next, 0, FilePos.LowPart, FilePos.HighPart, &ov);
    }

    // Wait until child process exits.
    WaitForSingleObject(piS.hProcess, INFINITE);

    // Close process and thread handles. 
    CloseHandle(piS.hProcess);
    CloseHandle(piS.hThread);


    return 0;
}

process B:

#include <windows.h>
#include <process.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <io.h>

#define MAX_LEN 100


int _tmain(int argc, LPTSTR argv[]){

    HANDLE read;
    DWORD n;
    int i = 0;
    TCHAR buffer[MAX_LEN], path[MAX_LEN];
    OVERLAPPED ov = { 0, 0, 0, 0, NULL };
    LARGE_INTEGER FilePos;

    read = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (read == INVALID_HANDLE_VALUE) {

        _tprintf(_T("Cannot open input file. Error: %x\n"),
            GetLastError());
        _tprintf(" \n Nome File: %s\n", argv[1]);
        return 2;
    }
    _tprintf(" \n Nome File APERTO: %s\n", argv[1]);

GetCurrentDirectory(MAX_LEN,path);
_tprintf(" \n path server: %s\n%s\n", path,argv[1]);



while (ReadFile(read, buffer, MAX_LEN*sizeof(TCHAR), &n, &ov) && n>0 ){


    if (n == 0){
        fprintf(stderr,"error readfle\n");
        return -5;
    }
    if (strncmp(buffer, ".end", 4) == 0){
        _tprintf(" \n STAMPA SERVER: esco\n");
        break;
    }

    _tprintf(" \n STAMPA SERVER: %s\n", buffer);



}



if (n == 0){
    fprintf(stderr, "error readfle\n");
    return -5;
}
    _tprintf("\n END SERVER");
    return 0;
}

Upvotes: 1

Views: 282

Answers (1)

Zotta
Zotta

Reputation: 2603

Do not use actual files for inter process communication. Use named pipes!

Search for CreateNamedPipe, there are plenty of examples.

Upvotes: 2

Related Questions