Sahil Gupta
Sahil Gupta

Reputation: 105

Why is write duplicating text in parent process?

I am reading Operating Systems Three Easy Pieces. While working through one of the exercises, I encountered an interesting behavior related to the 'write' system call. The program is as follows,

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <errno.h>

int main() 
{
    int fd = open("./some_file.txt", O_CREAT | O_WRONLY | O_APPEND, 0777);
    int rc =  fork();
    if (rc < 0) 
    {
        printf("Fork failed\n");
        exit(10);
    }
    else if (rc == 0) 
    {
        write(fd, "the sun shines so bright\n", 26);
    }
    else
    {
        wait(NULL);
        int e = write(fd, "it's a cold night outside \n", 36);
        if (e == -1)
        {
            printf("error writing to fd, %s", strerror(errno));
            exit(-1);
        }
    }
    return 0;
}

As the parent process waits for the child process to finish, the output of this program is,

the sun shines so bright
it's a cold night outside

which is expected. However, if I change the # of bytes to write in child process from 26 to 36,

write(fd, "the sun shines so bright\n", 36);

the output changes to

the sun shines so bright
it's a colit's a cold night outside

_________^ 10 bytes

The child process string (the sun shines so bright\n\0) is 26 bytes. The additional 10 bytes are causing this behavior. I have tried different values for the write statement in child process and the behavior is consistent. Can someone please explain why this is happening?

Upvotes: 1

Views: 41

Answers (1)

Brendan
Brendan

Reputation: 37222

Can someone please explain why this is happening?

For write(fd, "the sun shines so bright\n", 26); there's only 25 bytes and then the zero terminator that shouldn't be written, but that zero terminator is probably just ignored by whatever you're using to display the file so it "works" (by accident, in a way that would break if you displayed the file a different way and the zero terminator in the middle of the file wasn't ignored).

For write(fd, "the sun shines so bright\n", 36); there's still only 25 bytes, then the zero terminator that shouldn't be written, then 10 more bytes of garbage that shouldn't be written. That garbage just happens to be the start of a completely different string, so (due to a combination of luck and undefined behavior) it actually writes "the sun shines so bright\n" then the ignored string terminator then "it's a col".

For write(fd, "it's a cold night outside \n", 36); there's only 26 bytes and then the zero terminator that shouldn't be written, and then 9 bytes of garbage the shouldn't be written. In this case (due to a combination of luck and undefined behavior) I'd assume the garbage just happens to be zeros. I'm honestly surprised that (due to a combination of luck and undefined behavior) it didn't end up writing "it's a cold night outside \n" then the ignored zero terminator then "error wri".

Upvotes: 2

Related Questions