-1

I'm trying to achieve the following: I read nr words from input text file and for each word I want to start a child process to modify the word and return it in an output text file. The output fluctuates, sometimes I get the words messed up ( apple banana into appbananale) and sometimes the output file is 20kb and it freezes the text editor.

int main(int argc, char **argv){

    int in, out, i, nr, k, j;
    char buffer[100];

    in = open(argv[1], O_RDONLY);
    if (in == -1){
        perror(NULL);
        return errno;
    }
    out = open(argv[2], O_WRONLY | O_CREAT, 0666);
    if (out == -1){
        perror(NULL);
        return errno;
    }
    if (read(in, buffer, 100) == -1){
        perror(NULL);
        return errno;
    }
    nr = 5;
    k=0;
    srand(time(NULL));
    char v[20];
    int l;
    j=0;
    pid_t pid;
    for (i=1;i<sizeof(buffer);i++){
        if (k == nr) break;

        if (buffer[i]=='\n'){
            k++;
            pid = fork();
            if (pid < 0)
                return errno;
            if (pid == 0){
                //for (l=0;l<j;l++)
                write (out, v, j);
                return 0;
            }
            j=0;
        }
        else{
            j++;
            v[j-1]=buffer[i];   
        }

    }


    return 0;
}


Flo
  • 29
  • 5
  • 2
    "rest is irrelevant". Not on Stackoverflow it isn't. Please read [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask). In particular, all Stackoverflow questions asking for debugging help requires posting of a [minimal verifiable example](https://stackoverflow.com/help/minimal-reproducible-example). – kaylum Dec 27 '19 at 20:10
  • 3
    When dealing with multiple processes accessing a shared resource you need to implement synchronisation so that the shared resource is accessed in a defined order. It seems you don't have that so the processes will be writing to the file in an interleaved and random order. – kaylum Dec 27 '19 at 20:11
  • What is `out`? Do you write to the same file descriptor from many processes at the same time? – choroba Dec 27 '19 at 20:12
  • 3
    Looks like `j` is uninitialised when it is used in `j++` which will result in undefined (unpredictable) behaviour. And yeah, the full code confirms you are missing synchronisation. – kaylum Dec 27 '19 at 20:23
  • I apologise, I put all the code. @kaylum You mean shm_open, mmap, etc. I thought I could make it without those because I'm really new to them. J gets 0, because I i put the number of the words in the input file so buffer[1] is \n. – Flo Dec 27 '19 at 20:24
  • `nr = buffer[0] + 1`. What is that intended to do? It is using the first byte of the file but that is likely to be an ascii character and not a decimal number as you seem to be intending with that use. – kaylum Dec 27 '19 at 20:30
  • 1
    Regarding `j`, that just moves the problem to this line: `for (l=0;l – kaylum Dec 27 '19 at 20:35
  • @kaylum You were right. I edited the code, i totally forgot about atoi. The problem right now is that the order of the words is random in the output file. – Flo Dec 27 '19 at 20:44
  • The random part is to do with synchronisation as already stated. See the answer below for one way to solve that part. – kaylum Dec 27 '19 at 20:47

1 Answers1

0

Each of your child processes is writing to the same output stream, and they're all running concurrently, so their outputs are mixed together.

Instead of writing one character at a time, write the whole line. Calls to write() to a local POSIX-conforming filesystem are atomic, so you won't get data mixed between each process.

So change the loop:

for (l=0;l<j;l++)
    write (out, v+l, 1);

to

write(out, v, j);

See Atomicity of `write(2)` to a local filesystem for various caveats about this.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • That fixed the bigger problem, but right now the words are in random order in the output file. – Flo Dec 27 '19 at 20:45
  • 2
    What's the point of forking child processes if they shouldn't all run at the same time? – Barmar Dec 27 '19 at 20:50
  • 1
    Why would you expect that to fix it? The problem is that all the child processes run at the same time, so they write in an unpredictable order. Why are you using child processes if you want everything to be written in order? – Barmar Dec 27 '19 at 21:14
  • How am I supposed to do it then, if I still want to modify and return each word in a different process. – Flo Dec 27 '19 at 21:19
  • You need some form of synchronization between the processes, so that child N waits for child N-1 before it writes. This is relatively complicated. – Barmar Dec 27 '19 at 21:22
  • Ok, I think it's alright even if the order is random. I would like to know if it can be done with shm_open, after each word ftruncate length(word) and mmap with offset starting from previous length - length(word). I know it's not that simple but can I use something like this? – Flo Dec 27 '19 at 21:39
  • That doesn't make them write in a specific order. You need something that coordinates between the child processes. – Barmar Dec 27 '19 at 22:10
  • Note: all those child processes will actually slow down the execution of the program – user3629249 Dec 28 '19 at 01:19