Note that this behavior isn't specific to getline.

Contents of 123.txt: 14991 arbitrary bytes

Code:

```
#include <stdio.h>                                                              
 
#include <stdlib.h>                                                             
 
#include <unistd.h>                                                             
 
#include <sys/types.h>                                                          
 
#include <sys/wait.h>                                                           
 
#include <sys/types.h>                                                          
 
#include <sys/stat.h>                                                           
 
#include <fcntl.h>                                                              
 
                                                                                
 
void h(FILE* fd) {                                                              
 
 (void)fd;                                                                      
 
 pid_t p = fork();                                                              
 
 if(!p) {                                                                       
 
  sleep(2);                                                                     
 
  exit(1);                                                                      
 
 } else if (p > 0){                                                             
 
  int s;                                                                        
 
  waitpid( p, &s,0);                                                            
 
 } else{                                                                        
 
  perror("Fork");                                                               
 
  exit(2);                                                                      
 
 }                                                                              
 
}                                                                               
 
                                                                                
 
int main() {                                                                    
 
 FILE* fd = fopen("123.txt", "r");
 if (!fd){
   perror("fopen");
   exit(2);
 }                                                                              
                                
 size_t limit = 10;                                                             
 while(limit--) {                                                               
 
  char output[10000] = {0};                                                     
 
  ssize_t retval = fread(output, 1, 9, fd);                                     
 
  fprintf(stderr, "fread: %zd\n", retval);                                      
 
  if (retval <= 0){                                                             
 
    exit(0);                                                                    
 
  }                                                                             
 
  h(fd);                                                                        
 
  retval = fread(output, 1, 4096, fd);                                          
 
  fprintf(stderr, "fread: %zu\n", retval);                                      
 
  if (retval <= 0){                                                             
 
    exit(1);                                                                    
 
  }                                                                             
 
  sleep(1);                                                                     
 
 }                                                                              
 
 fclose(fd);                                                                    
 
 return 0;                                                                      
 
} 
```

Expected output: 
```
fread: 9
fread: 4096
fread: 9
fread: 4096
fread: 9
fread: 4096
fread: 9
fread: 2667
fread: 0
```

Actual output:
```
fread: 9
fread: 4096
fread: 9
fread: 4096
fread: 9
fread: 4096
fread: 9
fread: 4096
fread: 9
fread: 4096
<doesn't terminate>
```

It seems that the origin of this problem is that block buffered input
streams in glibc perform calls to `lseek(2)` right before program
termination. The `lseek()` call appears to reset the file descriptor
offset to one after the last byte that was actually flushed out to user
buffers

e.g if `getline` reads "hello\n" from a file containing "hello\nworld",
the program calls `lseek(3, -6, SEEK_CUR)` at program exit. This can be
confirmed using the strace tool.


This can be resolved by flushing input buffers prior to calling fork(). So 
whether this is a bug or feature remains to be seen.

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1750173

Title:
  getline doesn't terminate after fork

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1750173/+subscriptions

-- 
ubuntu-bugs mailing list
ubuntu-bugs@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to