Command executed through popen() hangs randomly

2.2k Views Asked by At

My program has this weird problem:

It tries to find a device by reading the output of some commands through a pipe:

FILE* fp = NULL;
fp = popen ("cd /sys/bus/usb/devices; grep -i NDI */product", "r");

and then uses fgets() to read the file stream and uses pclose() to close the pipe.

In a single thread program it worked well. However, after I integrated it into a multi-thread program, the fgets() function began to block the thread randomly.

After checking, I found that fgets() blocks because sometimes fp is returned as an empty file stream. After I set the status of fp to non-blocking and use read() to read the file by its ID, I can see read() returns -1 because of the empty file stream and then pclose() hangs. All these happen randomly.

So I think in this case the command executed through popen() hangs and never terminates. But WHY it happens randomly? The multi-thread program only has another thread for user interface interaction. I would assume it is fine since the pipe is only used locally.

Any ideas are appreciated. Thanks!


UPDATE

strace shows that sometimes the child process calls futex() after a bunch of munmap() calls and then hangs there: futex(0xb72eaf00, FUTEX_WAIT_PRIVATE, 2, NULL

In a normal case futex would not be called.

For reference, the output of strace in main process:

1344962944.530384 pipe2([26, 27], O_CLOEXEC) = 0
1344962944.530441 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb41a8a68) = 25529
1344962944.534683 close(27)             = 0
1344962944.534801 fcntl64(26, F_SETFD, 0) = 0
1344962944.534852 write(1, "entering fgets\n", 15) = 15
1344962944.534924 fstat64(26, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
1344962944.534992 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb377d000
1344962944.535065 read(26, 

The output of strace for child process shell:

1344962944.534652 set_robust_list(0xb41a8a70, 0xc) = 0
1344962944.534790 getpid()              = 25529
1344962944.534843 getppid()             = 25453
1344962944.534917 close(12)             = 0
1344962944.534983 munmap(0xa8fff000, 1048576) = 0
...
1344962944.535925 munmap(0xb2728000, 118784) = 0
1344962944.535952 close(11)             = 0
1344962944.535980 close(10)             = 0
1344962944.536018 futex(0xb72eaf00, FUTEX_WAIT_PRIVATE, 2, NULL
0

There are 0 best solutions below