compiling with gcc hw2.c -o x -lpthread
free(): invalid size
free(): invalid size
free(): invalid size
nano infile.txt
I'm assuming it has something to do with the file pointer maybe? the semaphores have been commented out to fix this issue first. All answers point to the pointer but switching things up isn't much help. I've tried compiling differently that doesn't help either.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
//sem_t X;
void process(){
//sem_open("X", O_CREAT,0777,0);
int ret;
int N = 1;
pid_t pid;
FILE* infile = fopen ("infile.txt", "r");
for(int i = 0; i< 50; i++){
fscanf (infile, "%d", &N);
fclose (infile);
printf("N: %d Process ID: %d",N,pid);
infile = fopen("infile.txt", "w");
N++;
//sem_post(&X);
fprintf(infile,"%d",N);
fflush(infile);
fclose(infile);
}
printf("\n");
int c;
//sem_getvalue(&X,&c);
printf(" \n \n \n%d",c);
}
int main(){
int pid, pid1, pid2;
pid = fork();
if(pid == 0){
//child1, Last
printf("Starting Process C: ");
process();
}
else{
pid1 = fork();
if(pid1 == 0){
//child2, Middle
printf("Starting Process B: ");
process();
}
else{
pid2 = fork();
if(pid2 == 0){
//child 3, First
printf("Starting Process A: ");
process();
}
else{
}
}
}
//sem_close(&X);
//sem_unlink(&X);
}
The most obvious problem is in your loop. I've removed everything but the fopen and fclose calls:
FILE* infile = fopen ("infile.txt", "r");
for(int i = 0; i< 50; i++){
fclose (infile);
infile = fopen("infile.txt", "w");
fclose(infile);
}
As you probably now see, when i is 1, you try to fclose(infile) - but that isn't open, hence the errors you get.
You need to move the first fopen into the loop - and check that opening the file and reading from it succeeds too:
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
void process() {
int N = 1;
for(int i = 0; i < 50; i++) {
FILE* infile = fopen("infile.txt", "r");
if(infile) {
bool readok = fscanf(infile, "%d", &N) == 1;
fclose(infile);
if(readok) { /* only do this if a value was read from the file ok */
printf("N: %d Process ID: %d", N, getpid());
infile = fopen("infile.txt", "w");
if(infile) {
N++;
fprintf(infile, "%d", N);
fflush(infile);
fclose(infile);
}
}
}
}
printf("\n");
exit(0); /* terminate this sub process */
}
int main() {
const size_t kPids = 3;
pid_t pids[kPids]; /* simplify keeping a number of background processes */
for(size_t i = 0; i < kPids; ++i) {
pids[i] = fork();
if(pids[i] == 0) {
printf("Starting Process %c:\n", (char)('A' + i));
process();
}
}
/* wait for children to finish */
pid_t pid;
int wstatus;
while((pid = wait(&wstatus)) != -1) {
printf("pid %d is done with status %d\n", pid, wstatus);
}
}
Your loop is problematic
FILE* infile = fopen ("infile.txt", "r"); //1
for(int i = 0; i< 50; i++){
fscanf (infile, "%d", &N);
fclose (infile); //2
printf("N: %d Process ID: %d",N,pid);
infile = fopen("infile.txt", "w"); //3
N++;
//sem_post(&X);
fprintf(infile,"%d",N);
fflush(infile);
fclose(infile); //4
}
You open the file at 1, then enter the loop, close it at 2, re-open it at 3 and re-close it at 4. In the next iteration, when you attempt to close at 2, you would hit into a double-free as it's already been closed at 4.
Related
Hi i need to take only 5 bytes from stdin, i've tried this but i have problem while executing it since it keeps asking me for input and at the end the string contained in buffer is wrong.
Also i'd like to know how to synchronize N processes while the parent is sleeping.
buffers[] is an array of buffers.
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define fflush(stdin) while (getchar() != '\n')
char **filenames;
int *files;
char **buffers;
int n_proc;
int main(int argc, char **argv) {
long i;
pid_t pid;
int status;
if(argc < 2) {
puts("Usage error: prog file1 ... fileN.\n");
exit(1);
}
filenames = argv + 1;
n_proc = argc - 1;
puts("Bef malloc buff.\n");
if((buffers = malloc(sizeof(char *) * n_proc)) == NULL) {
puts("Buffers' malloc error.\n");
exit(1);
}
if((files = malloc(sizeof(int) * n_proc)) == NULL) {
puts("Files' malloc error.\n");
exit(1);
}
puts("After malloc buff.\n");
for(i = 0; i < n_proc; i++) {
if((files[i] = open(filenames[i], O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) {
printf("Error while opening file %ld.\n", i);
exit(1);
}
}
puts("After file open.\n");
for(i = 0; i < n_proc; i++) {
if((buffers[i] = (char *) mmap(NULL, 1028, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0)) == NULL) {
printf("Error in mapping buffer %ld.\n", i);
exit(1);
}
}
puts("After mapping.\n");
i = 0;
while(i < n_proc) {
printf("Fork %ld started.\n", i);
pid = fork();
if(pid < 0) {
printf("Error while forking %ld.\n", i);
exit(1);
} else if(pid == 0) {
puts("Please insert an input of max 5 characters.\n");
printf("Son %ld.\n", i);
fflush(stdout);
fgets(buffers[i], 6, stdin);
buffers[i][strcspn(buffers[i], "\n")] = 0;
//int j;
//for(j = 0; j < 5; j++)
//buffers[i][j] = getchar();
//printf("Buff has %s inside.\n", buff);
//fflush(stdout);
fflush(stdin);
//strcpy(buffers[i], buff);
printf("Buffer %d has string %s inside.\n", i, buffers[i]);
fflush(stdout);
write(files[i], buffers[i], 6);
} else {
printf("Parent %ld.\n", i);
wait(&status);
}
i++;
}
}
This is only a prototype of the code, since there's still synchronization needed and signal handling
Code requires when to write on command line N files and creating N processes that each take 5 bytes from stdin and put in their own file.
As an example if i try with
./a.out hello.txt hello1.txt
Bef malloc buff.
After malloc buff.
After file open.
After mapping.
Fork 0 started.
Parent 0.
Please insert an input of max 5 characters.
Son 0.
Hello
Hello
Buffer 0 has string Hello inside.
Hello
Fork 1 started.
Parent 1.
Please insert an input of max 5 characters.
Son 1.
Hello
Hello
Buffer 1 has string Hello inside.
Hello
Fork 1 started.
Parent 1.
Please insert an input of max 5 characters.
Son 1.
As you can see it doesn't take the input and keeps asking for it, same problem with the getchar().
Note that in case stdin is associated with a terminal, there may also be input buffering in the terminal driver, entirely unrelated to stdio buffering. (Indeed, normally terminal input is line buffered in the kernel.) This kernel input handling can be modified using calls like tcsetattr(3); (stdin(3) man page)
If you give it the input "12345\n":
#include <stdio.h>
int main(void) {
char buffers[1][5];
unsigned i = 0;
for(unsigned j = 0; j < 5; j++)
buffers[i][j] = getchar();
printf("%.5s", buffers[i]);
// read the newline. You may need to discard others.
int ch = getchar();
if(ch == '\n')
printf("\n");
return 0;
}
it will print:
12345
I'm using a Linux 2.0.26 VM and never have this problem.
The while loop works because I added a printf inside it in order to test it.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{
int i;
mknod("pipe.txt", S_IFIFO | 0666, 0);
for (i = 0; i < 2; i++) {
if (fork() == 0) {
if (i == 0)
to_pipe();
//else
// pipe_a_archivo();
}
}
wait(NULL);
unlink("pipe.txt");
}
void to_pipe()
{
int num, fdini;
fdini = open("pipe.txt", O_WRONLY);
do {
//printf("Test");
scanf("%d", &num);
write(fdini, &num, sizeof(int));
} while (num != 0);
close(fdini);
unlink("pipe.txt");
exit();
}
This program should get numbers from keyboard and write them in a file. My problem is that whenever I execute the program from the command line, nothing happens, scanf() doesn't work because it doesn't let me input any number. I know for sure that the loop works because if uncomment printf() it prints on the screen. Any help on solving this problem?
I think that most of your problem is due to you not implementing the pipe_a_archivo() function to read from the FIFO and write the data to a file. Certainly, the code in the question is not a good MCVE (Minimal, Complete, Verifiable Example). Amongst other problems, there is no action for the second iteration of the loop.
This code error checks function calls, and includes a plausible implementation of pipe_a_archivo(), and then works sensibly:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
static void to_pipe(void);
static void pipe_a_archivo(void);
#define FIFO_NAME "pipe.txt"
#define FILE_NAME "archive.txt"
int main(void)
{
if (mkfifo(FIFO_NAME, 0666) != 0)
{
fprintf(stderr, "failed to create FIFO '%s'\n", FIFO_NAME);
exit(EXIT_FAILURE);
}
if (fork() == 0)
to_pipe();
if (fork() == 0)
pipe_a_archivo();
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
printf("PID %d exited with status 0x%.4X\n", corpse, status);
unlink("pipe.txt");
}
static void to_pipe(void)
{
int num, fdini;
fdini = open(FIFO_NAME, O_WRONLY);
do
{
printf("Enter a number: ");
fflush(stdout);
scanf("%d", &num);
write(fdini, &num, sizeof(int));
} while (num != 0);
close(fdini);
exit(0);
}
static void pipe_a_archivo(void)
{
int fd_in = open(FIFO_NAME, O_RDONLY);
if (fd_in < 0)
{
fprintf(stderr, "Failed to open FIFO '%s' for reading\n", FIFO_NAME);
exit(EXIT_FAILURE);
}
FILE *fp_out = fopen(FILE_NAME, "w");
if (fp_out == NULL)
{
fprintf(stderr, "Failed to open file '%s' for writing\n", FILE_NAME);
exit(EXIT_FAILURE);
}
int num;
while (read(fd_in, &num, sizeof(num)) == sizeof(num))
{
fprintf(fp_out, "%d\n", num);
}
close(fd_in);
fclose(fp_out);
exit(0);
}
I removed the loop in main() because a loop that tests which iteration it is on and then calls an appropriate function is really not a good design. This code also only deletes the FIFO in the main program, and only after both child processes have exited.
Sample run:
$ ./fifo29
Enter a number: 23
Enter a number: 34
Enter a number: 12931344
Enter a number: 0
PID 10939 exited with status 0x0000
PID 10940 exited with status 0x0000
$ cat archive.txt
23
34
12931344
0
$
I have the following code. It generates n child and then a random number between 0 and n. So that random number lets suppose is "i". The child number i must kill his brothers.
The problem is that the kill function is not killing anything since both ptree after and before are exactly the same.
I cant found a solution, the output must be the father and the i child only since all his brothers were killed by him.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <math.h>
char archSalidaAntes[] = "aprocesosAntes.txt";
char archSalidaDespues[] = "aprocesosDespues.txt";
void imprimirArreglo(int arr[], int n){
int i;
for(i=0; i<n; i++){
printf("%d\t", arr[i]);
}
printf("\n");
}
void imprimirArbolTxt(char nombreArchivo[], pid_t id){
char buff[255];
sprintf(buff, "pstree -p -c -l %d > %s", (int)id, nombreArchivo);
system(buff);
}
void communicateSon(int arrProc[], int n, int fd[]){
int i;
int data;
int writeResp;
close(fd[0]); //closing input
for(i=0; i<n; i++){
data = arrProc[i];
writeResp = write(fd[1], &data, sizeof(data));
if(!writeResp){
printf("error writing");
}
}
close(fd[1]); //closing output
}
void killOthers(int n, int fd[], int randInt){
int i;
int readResp;
int killResp;
int data;
int arrProc[n];
close(fd[1]); //closing output
i = 0;
while(1){
readResp = read(fd[0], &data, sizeof(data));
fflush(stdout);
fflush(stdin);
if(!readResp){
break;
}
arrProc[i] = data;
i++;
}
imprimirArreglo(arrProc, n);
printf("id elegido: %d\n", getpid());
for(i=0; i<n; i++){
if(i!= randInt){
printf("killing: %d\n", arrProc[i]);
killResp = kill((pid_t)arrProc[i], SIGKILL);
if(killResp < 0){
printf("error kill: %d \n", killResp);
}
int aux = kill(arrProc[i], 0);
printf("aux: %d\n", aux);
}
}
close(fd[0]); //closing input
char com[30];
sprintf(com, "pstree -p %d", getppid());
system(com);
}
int main(int argc, char **argv){
int n;
int i;
int *arrProc;
int randInt;
int fd[2];
pid_t pId;
n = atoi(argv[1]);
printf("n = %d\n", n);
srand(time(NULL));
arrProc = (int*) malloc(sizeof(int) * n);
randInt = rand() % n;
pipe(fd);
for(i=0; i<n; i++){
pId = fork();
if(pId){
arrProc[i] = (int)pId;
if(i == (n-1)){
char com[30];
sprintf(com, "pstree -p %d", getppid());
system(com);
communicateSon(arrProc, n, fd);
waitpid(arrProc[randInt], NULL, 0);
printf("termino la espera del hijo\n");
free(arrProc);
}
} else if(pId == 0){ //hijos
if(i==randInt){
killOthers(n, fd, randInt);
exit(0);
} else{
break;
}
}
}
sleep(0.5);
return 0;
}
Since main process never calls waitpid for other children all of them become zombies after getting killed.
Update: you should also close pipe ends descriptors in other child processes prior to putting them to sleep, otherwise killer child process will get stuck at waiting for more data to come from the pipe.
} else{
close(fd[0]);
close(fd[1]);
break;
}
Update: sleep takes unsigned int number of seconds, so sleep(0.5) will be equivalent to sleep(0).
Try with sleep(1).
The sleep() function wants an integer argument, so sleep(0.5) equals to zero - which is probably not "long enough" for your demo to work. The child processes may terminate before the kill signal can reach them.
The program has to do it:
A process P0 creates P1 and P2;
sizeof(buffer) = N (inserts with command line);
P1 inserts random values in the first N/2 elements of the buffer (N insert by user)
P2 inserts random values in the second part of the buffer
After that: P1 inverts the second part of the buffer and then the process P0 print all elements of it
If the user presses CTRL+C ---> print the buffer elements and kill all process;
I don't know why , but process P1 remains in pause. I called in the concurrent process P2 the increase of the semaphore's value ("semaphore_inv") and the wait has to decrease it to 0. For this reason the program doesn't work correctly.
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
int N;
int buff[1024];
void print(int sig) {
int i;
for(i=0; i<N; i++) {
printf("Slot %d of the buffer is %d\n",i, buff[i]);
}
kill(0,SIGKILL);
}
void main (int argc, char* argv[]) {
int p1, p2;
sem_t semaphore_inv;
sem_t semaphore_read;
sem_t semaphore_write;
struct sembuf sembuf;
N=atoi(argv[1]);
if (N<=0 || N>=1024) {
printf("Inserirt a value > 0 and < 1024\n");
exit(-1);
}
if (argc!=2) {
printf("Insert com N\n");
exit(1);
}
int buffer[N];
//I insert this type of semaphore only to try it
int sem_write = semget(IPC_PRIVATE,1,IPC_CREAT|0666);
if (sem_write <0) printf("Error in the semaphore creation\n");
int sem_write_b = sem_init(&semaphore_write,1,1);
if (sem_write_b<0) printf("Error in the semaphore creation\n");
int sem_inv = sem_init(&semaphore_inv, 1, 0);
if (sem_inv<0) printf("Error in the semaphore creation\n");
int sem_read = sem_init(&semaphore_read,1,0);
if (sem_read<0) printf("Error in the semaphore creation\n");
int ret = semctl(sem_write, 0, SETVAL, 1);
if (ret == -1) printf("Error: semctl, with errno %s\n", strerror(errno));
signal(SIGINT, print);
p1 = fork();
p2 = fork();
if (p1 < 0) {
printf("P1: error, fork\n");
exit(-2);
}
if (p2 < 0) {
printf("P2: error, fork\n");
exit(-2);
}
if (p1==0) {
loop:
sembuf.sem_num=0;
sembuf.sem_op= -1;
sembuf.sem_flg=0;
semop(sem_write, &sembuf, 1);
int i;
for (i=0; i<N/2; i++) {
buffer[i] = rand();
printf("P1: the insert value in buffer[%d] is %d\n",i , buffer[i]);
}
sem_wait(&semaphore_inv);
printf("P1: i'm going to invert the second part of the buffer\n");
int j=1;
for (i=N/2; i<N; i++){
int buffer_prev;
buffer_prev=buffer[i];
buffer[i] = buffer[N-j];
buffer[N-j] = buffer_prev;
j++;
}
sem_post(&semaphore_read);
sleep(1);
goto loop;
}
if (p2==0) {
loop_b:
sem_wait(&semaphore_write);
int i;
for (i=N/2; i<N; i++) {
buffer[i] = rand();
printf("P2: the value insert in buffer[%d] is %d\n", i, buffer[i]);
}
sem_post(&semaphore_inv);
sleep(1);
goto loop_b;
}
else{
sem_wait(&semaphore_read);
int k;
for (k=0; k<N; k++) {
buff[k] = buffer[k];
printf(" slot %d of the buffer is %d\n", buffer[k]);
}
sem_post(&semaphore_write);
sembuf.sem_num=0;
sembuf.sem_op= +1;
sembuf.sem_flg=0;
semop(sem_write, &sembuf, 1);
}
}
There are four processes involved. Illustration:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int pid = -2, pid1 = -2, pid2 = -2;
pid1 = fork();
pid2 = fork();
mypid = getpid();
printf("Pid= {%d, %d %d}\n", mypid, pid1,pid2);
return 0;
}
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main ()
{
/* Create the pipe */
pid_t pid;
int k;
pid = fork ();
if (pid < 0)
{
printf ("Fork Failed\n");
return -1;
}
for(k=0;k<60;k++)
{
if (pid == 0)
{
printf("I'm the child\n");
printf("my pid is %d\n",getpid());
FILE *fp,*fp1;
int i;
/* open the file */
fp = fopen("File1.txt ", "r");
fscanf(fp, "%d", &i) ;
printf("i: %d and pid: %d",i,pid);
fclose(fp);
fp1= fopen("File1.txt ", "w");
fprintf(fp, "%d", i++);
fclose(fp1);
sleep(1);
}
else
{
printf("I'm the parent\n");
printf("my pid is %d\n",getpid());
FILE *fp,*fp1;
int i;
int y;
/* open the file */
fp = fopen("File1.txt ", "r");
fscanf(fp, "%d", &i) ;
printf("i: %d and pid: %d",i,pid);
fclose(fp);
fp1= fopen("File1.txt ", "w");
fprintf(fp, "%d", i++);
fclose(fp1);
sleep(1);
}
}
return 0;
}
I got an error i.e segmentation fault core dumped after executing this code. I would like to know where I did wrong. My main motto is: I want to read a file that contains a number 1and print that number.
I want to write the same file and increment that number by 1.After that the child or parent goes into sleep mode and then parent or child performs the same procedure again. This process continues up to 60 times .
You are writing to the wrong file descriptor in both parent and child.
The following line:
fprintf(fp, "%d", i++);
should be:
fprintf(fp1, "%d", i++);
Indeed you have already closed fp before.