Home > Net >  Write() works even if i blocked my file by other process
Write() works even if i blocked my file by other process

Time:12-24

When I run my program:

int i = fork();

if (!i){
    int id = open("shared.txt", 0600 | O_WRONLY);
    if(flock(id, LOCK_EX | LOCK_NB) == -1)
        perror("flock_ch");
if(write(id, "child", 5)) printf("child did it\n");
else perror("write_ch");
sleep(3);
    close(id);
}
else {
    int id = open("shared.txt", 0600 | O_WRONLY);
    if(flock(id, LOCK_EX | LOCK_NB) == -1)
       perror("flock_PR");
if(write(id, "parent", 6)) printf("parent did it\n");
else perror("write_pr");
sleep(3);
    close(id);
}

wait(NULL);

I expect that only one process will write something in the file, but even if the file is locked, two of processes write in the file.

CodePudding user response:

Both processes are writing to the file because you're ignoring the error return value from flock(). When I run your code, I see:

parent did it
flock_ch: Resource temporarily unavailable
child did it

That flock_ch: Resource temporarily unavailable is because flock() is returning with an error and telling you the file is locked. You're printing out an error message, but not otherwise responding to the error message. You probably want to either (a) exit or (b) loop until flock() succeeds.

Using a loop might look like:

#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <unistd.h>

#define LOCK_FLAGS (LOCK_EX | LOCK_NB)

void parent() {
  int fd = open("shared.txt", 0600 | O_WRONLY);

  while (flock(fd, LOCK_FLAGS) == -1) {
    printf("parent waiting for lock\n");
    sleep(1);
  }
  printf("parent acquired lock\n");

  if (write(fd, "parent", 6) >= 0) {
    printf("parent wrote to file\n");
  } else {
    perror("parent: write failed:");
    exit(1);
  }

  sleep(3);

  close(fd);
}

void child() {
  int fd = open("shared.txt", 0600 | O_WRONLY);

  while (flock(fd, LOCK_FLAGS) == -1) {
    printf("child waiting for lock\n");
    sleep(1);
  }
  printf("child acquired lock\n");

  if (write(fd, "child", 6) >= 0) {
    printf("child wrote to file\n");
  } else {
    perror("child: write failed:");
    exit(1);
  }

  sleep(3);

  close(fd);
}

int main() {
  // ensure "shared.txt" exists
  int fd = open("shared.txt", O_CREAT | O_WRONLY, 0600);
  close(fd);

  pid_t pid = fork();

  if (pid == 0) {
    child();
    exit(0);
  }
  parent();
  wait(NULL);

  return 0;
}

Running the above produces:

parent acquired lock
parent wrote to file
child waiting for lock
child waiting for lock
child waiting for lock
child acquired lock
child wrote to file

Alternately, drop the LOCK_NB flag so that flock() blocks until the lock is available. That might look like:

#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <unistd.h>

#define LOCK_FLAGS (LOCK_EX) // | LOCK_NB)

void parent() {
  int fd = open("shared.txt", 0600 | O_WRONLY);

  if (flock(fd, LOCK_FLAGS) == -1) {
      perror("parent: flock:");
      exit(1);
  }

  printf("parent acquired lock\n");

  if (write(fd, "parent", 6) >= 0) {
    printf("parent wrote to file\n");
  } else {
    perror("parent: write failed:");
    exit(1);
  }

  sleep(3);

  close(fd);
}

void child() {
  int fd = open("shared.txt", 0600 | O_WRONLY);

  if (flock(fd, LOCK_FLAGS) == -1) {
      perror("child: flock:");
      exit(1);
  }

  printf("child acquired lock\n");

  if (write(fd, "child", 6) >= 0) {
    printf("child wrote to file\n");
  } else {
    perror("child: write failed:");
    exit(1);
  }

  sleep(3);

  close(fd);
}

int main() {
  // ensure "shared.txt" exists
  int fd = open("shared.txt", O_CREAT | O_WRONLY, 0600);
  close(fd);

  pid_t pid = fork();

  if (pid == 0) {
    child();
    exit(0);
  }
  parent();
  wait(NULL);

  return 0;
}

And running the above produces:

parent acquired lock
parent wrote to file
child acquired lock
child wrote to file
  • Related