Communication Issue Between Concurrent Processes Using Pipes in C

The program uses pipes to manage multiple concurrent processes. When the program needs to write to pipe2 to then share it with the concurrent printToFile process, it stops functioning correctly because when I read from pipe2 in printToFile, nothing is read. The exact reason for this interruption is unclear, and further debugging is needed to identify the cause of this problem.

Through some debugging with various prints inserted here and there, I have been able to narrow down that the problem lies in the printToFile function or at the end of the createTable function when writing to pipe2[1] in write mode.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>

// Definition of the structure for an object containing a string, its frequency, and coordinates in the matrix
typedef struct {
    wchar_t string[31];
    float frequency;
    int occurrence;
    int x;
    int y;
} Object;

// Definition of the structure for a matrix containing a list of objects and its dimensions
typedef struct {
    Object** list;
    int x;
    int y;
} Matrix;

// Definition of the structure for the alphabet containing a sub-alphabet and a word
struct Alphabet {
    struct Alphabet* subAlphabet[46];
    Object *word;
};

// Definition of the type Dictionary as a pointer to struct Alphabet
typedef struct Alphabet Dictionary;

// Declaration of the recursive deallocation function
Dictionary* deallocate(Dictionary* dict);
int createTable(FILE* file, int index, Matrix* matrix, Dictionary* dict, int pipe1[], int pipe2[], wchar_t firstWord[]);
int asciiIndex(wchar_t character);
bool compareStrings(wchar_t* string1, wchar_t* string2);
bool operationalSearch(wchar_t string[], int index, Dictionary* dict, int i, int p, Matrix* m);
void readWordFromFile(FILE* file, int pipe1[], long int position);
void printToFile(FILE* sheet, int pipe2[], int MAX);
long int getFirstWord(FILE* file, Matrix* matrix);

int main() { // Declare the main function

    setlocale(LC_ALL, "it_IT.UTF-8"); // Set a locale that supports Unicode

    FILE* file = fopen("test.txt", "r");
    FILE* sheet = fopen("output.csv", "w");
    if (file == NULL || sheet == NULL) { // If either file does not open
        exit(EXIT_FAILURE); // Exit with an error
    }

    Dictionary* dictionary = (Dictionary*)calloc(1, sizeof(Dictionary)); // Allocate the dictionary
    dictionary->word = (Object*)calloc(1, sizeof(Object)); // Allocate a word in the dictionary

    Matrix matrix; // Declare a matrix

    matrix.list = (Object**)calloc(1, sizeof(Object*));
    matrix.list[0] = (Object*)calloc(2, sizeof(Object));

    long int position = getFirstWord(file, &matrix);
    if (position == -1) {
        exit(EXIT_FAILURE); // Exit with an error
    }

    int pipe1[2], pipe2[2]; // Declare two pipes

    if (pipe(pipe1) == -1 || pipe(pipe2) == -1) { // If pipe creation fails
        exit(EXIT_FAILURE); // Exit with an error
    }
    int MAX; // Maximum number of bytes to allocate in a row in the matrix
    pid_t pid_Process1, pid_Process2, pid_Process3; // Declare the PIDs of the processes

    pid_Process1 = fork(); // Create the first process
    if (pid_Process1 == -1) { // If fork fails
        perror("Fork error"); // Print an error
        return 1; // Return 1
    } else if (pid_Process1 == 0) { // If in the child process
        close(pipe1[0]); // Close the read end of pipe1
        readWordFromFile(file, pipe1, position); // Call the readWordFromFile function
        exit(0); // Exit the process
    } else { // If in the parent process
        close(pipe1[1]); // Close the write end of pipe1
        waitpid(pid_Process1, NULL, 0); // Wait for the termination of process 1
    }

    pid_Process2 = fork(); // Create the second process
    if (pid_Process2 == -1) { // If fork fails
        perror("Fork error"); // Print an error
        return 1; // Return 1
    } else if (pid_Process2 == 0) { // If in the child process
        close(pipe2[0]); // Close the read end of pipe2
        wchar_t firstWordArray[31]; // Ensure the size is sufficient
        wcscpy(firstWordArray, matrix.list[0][0].string);
        MAX = createTable(file, 0, &matrix, dictionary, pipe1, pipe2, firstWordArray); // Call the createTable function which returns the maximum number of bytes of the matrix rows
        exit(0); // Exit the process
    } else { // If in the parent process
        close(pipe1[0]); // Close the read end of pipe1
        close(pipe2[1]); // Close the write end of pipe2
        waitpid(pid_Process2, NULL, 0); // Wait for the termination of process 2
    }

    pid_Process3 = fork(); // Create the third process
    if (pid_Process3 == -1) { // If fork fails
        perror("Fork error"); // Print an error
        return 1; // Return 1
    } else if (pid_Process3 == 0) { // If in the child process
        close(pipe2[1]); // Close the write end of pipe2
        printToFile(sheet, pipe2, MAX); // Call the printToFile function
        close(pipe2[0]); // Close the read end of pipe2
        exit(0); // Exit the process
    }
    waitpid(pid_Process3, NULL, 0); // Wait for the termination of process 3

    wait(NULL); // Wait for the termination of all child processes
    wait(NULL); // Wait for the termination of all child processes
    wait(NULL); // Wait for the termination of all child processes

    fclose(sheet); // Close the output file
    fclose(file); // Close the input file

    for (int i = 0; i < 46; i++) { // Free the memory of the dictionary
        dictionary->subAlphabet[i] = deallocate(dictionary->subAlphabet[i]); // Call the deallocate function
    }
    free(dictionary->word); // Free the memory of the word
    free(dictionary); // Free the memory of the dictionary

    return 0; // Return 0
}

Dictionary* deallocate(Dictionary* dict) { // Declare the deallocation function
    if (dict == NULL) { // If the dictionary is NULL
        return NULL; // Return NULL
    }

    for (int i = 0; i < 46; i++) { // Iterate over the 46 elements of the sub-alphabet
        dict->subAlphabet[i] = deallocate(dict->subAlphabet[i]); // Call the deallocation function recursively
    }
    free(dict->word); // Free the memory of the word
    free(dict); // Free the memory of the dictionary
    return NULL;
}

// Function to get the ASCII index of a character
int asciiIndex(wchar_t character) {
    // Convert the character to lowercase
    wchar_t c = towlower(character);

    if (iswalpha(c)) {
        // Handle non-accented letters
        return c - L'a';
    } else {
        // Handle accented characters
        switch (c) {
            case L'à': return 26;
            case L'è': return 27;
            case L'é': return 28;
            case L'ì': return 29;
            case L'ò': return 30;
            case L'ù': return 31;
            case L'!': return 32;
            case L'?': return 33;
            case L'.': return 34;
            case L''': return 35;
        }
    }

    // Handle numbers
    if (c >= L'0' && c <= L'9') {
        return 36 + (c - L'0');
    }

    // Unrecognized character
    return -1;
}

// Function to compare two strings
bool compareStrings(wchar_t* string1, wchar_t* string2) { // Declare the compareStrings function
    if (*string1 == L'' && *string2 == L'') { // If both strings are terminated
        return true; // Return true
    }
    
    if (*string1 == *string2 || (towlower((wchar_t)*string1) == towlower((wchar_t)*string2))) { // Check if the characters are equal or if they are equal in lowercase
        return compareStrings(string1 + 1, string2 + 1); // Recursively call the function on the next character
    }

    return false; // If the characters are not equal, return false
}

// Function to find the first word in the file
long int getFirstWord(FILE* file, Matrix* matrix) {
    char character;
    const wchar_t* accentedCharacters = L"àèéìòóùÀÈÉÌÒÓÙ";
    int index = 0; // Initialize the index to 0
    long int pos = 0; // Initialize pos to 0

    while ((character = fgetwc(file)) != WEOF) {
        wchar_t next = fgetwc(file);
        fseek(file, -1, SEEK_CUR);
        if (character == L'n' || character == L' ') { // If the first characters are n or space, skip them
            continue;
        } else if (iswalnum(character) || (wcschr(accentedCharacters, character) != NULL)) { // If you find or when you find alphanumeric characters, then add to the matrix in the first position
            matrix->list[0][0].string[index] = character;
            index++;
            if (next == L' ' || next == L'n' || next == L'!' || next == L'?' || next == L'.') { // If followed by space or newline, terminate the string
                matrix->list[0][0].string[index] = L'';
                return ftell(file);
            } else if (next == L''') { // If followed by an apostrophe, append the apostrophe and terminate the string and the first word
                matrix->list[0][0].string[index] = L''';
                matrix->list[0][0].string[index + 1] = L'';
                return ftell(file);
            }
            continue;
        } else if (character == L'!' || character == L'?' || character == L'.') { // If you encounter special characters, add them to the matrix as separate characters
            matrix->list[0][0].string[index] = character;
            matrix->list[0][0].string[index + 1] = L'';
            return ftell(file);
        }
    }
    
    // If we reach here, it means we have reached the end of the file without finding a valid word
    return -1; // Return -1 to indicate that a valid word was not found
}

// Function for operational search of a string in the matrix
bool operationalSearch(wchar_t string[], int index, Dictionary* dict, int i, int p, Matrix* m) { // Declare the operationalSearch function
    Dictionary* currentDict = dict; // Initialize currentDict with dict
    int ASCII; // Declare the ASCII variable

    if (string[index] == '') { // If the current character is the string terminator
        if (compareStrings(currentDict->word->string, m->list[i][0].string)) { // If the string of the dictionary word is equal to the matrix string
            int n = 1; // Initialize n to 1
            int y = currentDict->word->y; // Assign the y coordinate of the dictionary word to y
            int x = currentDict->word->x; // Assign the x coordinate of the dictionary word to x
            int found = 0; // Initialize found to 0

            m->list[y][0].occurrence++; // Increment the occurrence of the word in the matrix
            while (n <= m->x && m->list[y][n].x == n) { // As long as n is less than or equal to the x dimension of the matrix and the matrix element is equal to n
                if (compareStrings(m->list[y][n].string, m->list[i][p].string)) { // If the current string is equal to the matrix string
                    m->list[y][n].occurrence++; // Increment the occurrence
                    m->list[y][n].frequency = (float)m->list[y][n].occurrence / (float)m->list[y][0].occurrence; // Calculate the frequency
                    found = 1; // Set found to 1
                }
                m->list[y][n].frequency = (float)m->list[y][n].occurrence / (float)m->list[y][0].occurrence; // Calculate the frequency
                n++; // Increment n
            }

            if (!found) { // If the string was not found
                if (n > m->x) { // If n is greater than the x dimension of the matrix
                    m->x = n; // Assign n to x
                }
                m->list[y] = realloc(m->list[y], (n + 1) * sizeof(Object)); // Reallocate memory for the row of the matrix
                wcscpy(m->list[y][n].string, m->list[i][p].string); // Copy the string to the matrix
                m->list[y][n].occurrence = 1; // Initialize the occurrence to 1
                m->list[y][n].frequency = (float)m->list[y][n].occurrence / (float)m->list[y][0].occurrence; // Calculate the frequency
                m->list[y][n].x = n; // Assign n to the x coordinate
            }

            return true; // Return true
        }

        wcscpy(currentDict->word->string, string); // Copy the string to the dictionary word
        currentDict->word->x = p; // Assign p to the x coordinate of the word
        currentDict->word->y = i; // Assign i to the y coordinate of the word
        m->list[i][1].x = 1; // Assign 1 to the x coordinate of the matrix
        m->list[i][0].x = 0; // Assign 0 to the x coordinate of the matrix
        m->list[i][1].occurrence = 1; // Initialize the occurrence to 1
        m->list[i][0].occurrence = 1; // Initialize the occurrence to 1
        m->list[i][1].frequency = (float)m->list[i][1].occurrence / (float)m->list[i][0].occurrence; // Calculate the frequency

        return false; // Return false
    }

    ASCII = asciiIndex(string[index]); // Calculate the ASCII index of the current character
    if (currentDict->subAlphabet[ASCII] == NULL) { // If the current sub-alphabet is NULL
        currentDict->subAlphabet[ASCII] = (Dictionary*)calloc(1, sizeof(Dictionary)); // Allocate memory for the sub-alphabet
        if (currentDict->subAlphabet[ASCII] == NULL) { // If the memory was not allocated
            exit(1); // Exit with an error
        }
        currentDict->subAlphabet[ASCII]->word = (Object*)calloc(1, sizeof(Object)); // Allocate memory for the sub-alphabet word
        if (currentDict->subAlphabet[ASCII]->word == NULL) { // If the memory was not allocated
            exit(1); // Exit with an error
        }
    }
    currentDict = currentDict->subAlphabet[ASCII]; // Assign the current sub-alphabet to currentDict
    return operationalSearch(string, index + 1, currentDict, i, p, m); // Recursively call the function
}

// Function to handle the end of a string
int createTable(FILE* file, int index, Matrix* matrix, Dictionary* dict, int pipe1[], int pipe2[], wchar_t firstWord[]) { // Declare the createTable function
    wchar_t string1[31]; // Declare a string of 31 characters
    matrix->x = 1; // Initialize the x dimension to 1
    matrix->y = 1; // Initialize the y dimension to 1
    matrix->list = NULL; // Initialize the list to NULL

    matrix->list = (Object**)calloc(1, matrix->y * sizeof(Object*)); // Allocate memory for the matrix
    matrix->list[matrix->y - 1] = (Object*)calloc(1, 2 * sizeof(Object)); // Allocate memory for a row of the matrix

    wcscpy(matrix->list[0][0].string, firstWord); // Copy the first word to the matrix

    // Read all words from pipe1 before writing to pipe2
    while (read(pipe1[0], &string1, sizeof(string1)) > 0) { // Read all words from pipe1
        if (string1[0] == '') { // If the string is empty
            break; // Exit the loop
        }

        // Add words as values to the Matrix data structure
        wcscpy(matrix->list[matrix->y - 1][1].string, string1); // Copy the string to the matrix
        matrix->list[matrix->y - 1][1].x = 1; // Assign 1 to the x coordinate
        matrix->list[matrix->y - 1][0].x = 0; // Assign 0 to the x coordinate

        int control = operationalSearch(matrix->list[matrix->y - 1][0].string, 0, dict, matrix->y - 1, 1, matrix); // Call the operationalSearch function
        if (control == 0) { // If control is 0
            matrix->y++; // Increment the y dimension
            matrix->list = realloc(matrix->list, matrix->y * sizeof(Object*)); // Reallocate memory for the matrix
            matrix->list[matrix->y - 1] = (Object*)calloc(1, 2 * sizeof(Object)); // Allocate memory for a new row
        }

        wcscpy(matrix->list[matrix->y - 1][0].string, string1); // Copy the string to the matrix
        string1[0] = ''; // Reset the string
    }

    // Handle the end
    wcscpy(matrix->list[matrix->y - 1][1].string, matrix->list[0][0].string); // Copy the first word to the last row
    int control = operationalSearch(matrix->list[matrix->y - 1][0].string, 0, dict, matrix->y - 1, 1, matrix); // Call the operationalSearch function
    if (control == 0) { // If control is 0
        matrix->y++; // Increment the y dimension
    }
    close(pipe1[0]); // Close pipe1

    int rowDim = 31; // Minimum dimension of each row
    int maxDim = 31; // Maximum dimension that a row in the matrix can assume

    // Write the rows of the matrix to pipe2
    for (int i = 0; i < matrix->y - 1; i++) { // Write the rows of the matrix to pipe2
        wchar_t* row = calloc(1, rowDim * sizeof(wchar_t)); // Buffer to store the string representation of the row, dynamically allocated
        int occurrences = 0; // Occurrence counter
 
        swprintf(row, rowDim, L"%ls", matrix->list[i][0].string);

        for (int j = 1; j < matrix->x + 1; j++) { // Iterate over the columns
            if (occurrences == matrix->list[i][0].occurrence) { // If occurrences are equal
                break; // Exit the loop
            }
            occurrences = occurrences + matrix->list[i][j].occurrence; // Increment occurrences
            int increment = wcslen(matrix->list[i][j].string) + 6; // Calculate the increment in bytes to add each time
            rowDim += increment; // Add to the dimension of that row
            if (rowDim > maxDim) { // Check if this corresponds to the maximum dimension of the longest row in the matrix
                maxDim = rowDim; // If so, assign that value
            }
            row = realloc(row, rowDim * sizeof(wchar_t)); // Extend the row buffer by reallocating it
            swprintf(row + wcslen(row), rowDim - wcslen(row), L",%ls,%.4f", matrix->list[i][j].string, matrix->list[i][j].frequency); // Add the string and the frequency
        }
        if ((i + 1) != matrix->y - 1) { // If it is not the last row
            swprintf(row + wcslen(row), rowDim - wcslen(row), L"%ls", L"n"); // Add a new line
        }
        wprintf(L"%ls", row);
        write(pipe2[1], row, sizeof(row)); // Write the string representation of the row to pipe2
    }
    close(pipe2[1]); // Close pipe2
    return maxDim; // Return maxDim
}

void printToFile(FILE* sheet, int pipe2[], int MAX) { // Declare the printToFile function
    close(pipe2[1]); // Close the write end of pipe2
    wchar_t row[MAX]; // Declare a buffer for the row with a byte dimension equal to the maximum dimension of the longest row in the matrix
    while (read(pipe2[0], row, sizeof(row)) > 0) { // Read from pipe2
        fwprintf(sheet, L"%ls", row); // Write the row to the file
    }
}

// Function to read the input file
void readWordFromFile(FILE* file, int pipe1[], long int position) {
    wchar_t string1[31];
    int index = 0;
    wchar_t character;
    const wchar_t* accentedCharacters = L"àèéìòóùÀÈÉÌÒÓÙ";
    fseek(file, position, SEEK_SET);

    while ((character = fgetwc(file)) != WEOF) {
        wchar_t next = fgetwc(file);
        fseek(file, -1, SEEK_CUR);

        if ((character == L' ' || character == L'n') && next == WEOF) {
            // Handle the case where the last character is a space or newline
            if (index > 0) {
                string1[index] = L'';
                write(pipe1[1], string1, sizeof(string1));
            }
            break;
        }

        if (character == L'!' || character == L'?' || character == L'.') {
            if (index > 0) {
                string1[index] = L'';
                write(pipe1[1], string1, sizeof(string1));
                index = 0;
            }
            string1[0] = character;
            string1[1] = L'';
            write(pipe1[1], string1, sizeof(string1));
            if (next == WEOF) {
                break;
            }
        } else if (iswalnum(character) || (wcschr(accentedCharacters, character) != NULL) || character == L''') {
            string1[index++] = character;
            if (next == L' ' || next == L'n' || next == WEOF ||
                next == L'!' || next == L'?' || next == L'.' || character == L''') {
                string1[index] = L'';
                write(pipe1[1], string1, sizeof(string1));
                index = 0;
            }
        } else if (character == L' ' || character == L'n') {
            if (index > 0) {
                string1[index] = L'';
                write(pipe1[1], string1, sizeof(string1));
                index = 0;
            }
        } else if (!(iswalnum(character) || (wcschr(accentedCharacters, character) != NULL) ||
                     character == L''' || character == L'!' ||
                     character == L'?' || character == L'.') &&
                   (next == L' ' || next == L'n')) {
            if (index > 0) {
                string1[index] = L'';
                write(pipe1[1], string1, sizeof(string1));
                index = 0;
            }
            continue;
        }

        if (next == WEOF) {
            break;
        }
    }

    close(pipe1[1]);
}

I tried using pipes to manage communication between multiple concurrent processes in a C program. Specifically, I expected the printToFile function to read data written by the createTable function through pipe2, but it failed to read anything. Further debugging is needed to identify the exact cause of this issue.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật