sakashita_spc
2019年7月4日 14時17分
お世話になります。
840/Atmark-distを使っています。
popenを使っているのですが、以下のようなコーディングは問題ないでしょうか?
int count;
FILE *f1,*f2;
f1=popen("XXXXX","r")
for(count=0;count<10;count++)
{
f2=popen("YYYYY","r");
....
pclose(f2);
}
pclose(f1);
最初にpopenしたのち、pcloseする前に、popenをするケース。
上記の関数は単純化したものですが、f1,f2は同一プロセス、スレッドでの実行です。
以上、アドバイスよろしくお願いします。
コメント
y.nakamura
中村です。
> *** glibc detected *** ./demo1: double free or corruption (out): 0x00012260 ***
> Aborted
>
> のエラーが出てしまいました。(外側のループのpclose()でのエラーですね。)
問題なく動くと思いますけど・・・
テストソース
#include <stdio.h> #include <errno.h> int main(int argc, char *argv[]) { int count; FILE *f1, *f2; char buf[1024]; f1 = popen("/bin/ps", "r"); if (f1 == NULL) { perror("popen f1"); return 1; } printf("-----------------------\n"); while (fgets(buf, sizeof buf, f1) != NULL) { printf("%s", buf); } printf("-----------------------\n"); for (count = 0; count < 5; count++) { printf("==== count=%d =====\n", count); f2 = popen("/bin/ls -la", "r"); if (f2 == NULL) { perror("popen f2"); return 1; } while (fgets(buf, sizeof buf, f2) != NULL) { printf("%s", buf); } if (pclose(f2) < 0) { perror("pclose f2"); return 1; } printf("==================\n"); } if (pclose(f1) < 0) { perror("pclose f1"); return 1; } return 0; }
(ループ10回でも試してますが、投稿にあたり、
結果が長くなるので5回にしました)
結果
----------------------- PID TTY TIME CMD 16915 pts/0 00:00:00 bash 17625 pts/0 00:00:00 a.out 17626 pts/0 00:00:00 sh 17627 pts/0 00:00:00 ps ----------------------- ==== count=0 ===== 合計 20 drwxr-xr-x 2 atmark atmark 4096 7月 5 02:52 . drwxr-xr-x 7 atmark atmark 4096 7月 5 02:34 .. -rwxr-xr-x 1 atmark atmark 5888 7月 5 02:52 a.out -rw-r--r-- 1 atmark atmark 830 7月 5 02:51 test.c ================== ==== count=1 ===== 合計 20 drwxr-xr-x 2 atmark atmark 4096 7月 5 02:52 . drwxr-xr-x 7 atmark atmark 4096 7月 5 02:34 .. -rwxr-xr-x 1 atmark atmark 5888 7月 5 02:52 a.out -rw-r--r-- 1 atmark atmark 830 7月 5 02:51 test.c ================== ==== count=2 ===== 合計 20 drwxr-xr-x 2 atmark atmark 4096 7月 5 02:52 . drwxr-xr-x 7 atmark atmark 4096 7月 5 02:34 .. -rwxr-xr-x 1 atmark atmark 5888 7月 5 02:52 a.out -rw-r--r-- 1 atmark atmark 830 7月 5 02:51 test.c ================== ==== count=3 ===== 合計 20 drwxr-xr-x 2 atmark atmark 4096 7月 5 02:52 . drwxr-xr-x 7 atmark atmark 4096 7月 5 02:34 .. -rwxr-xr-x 1 atmark atmark 5888 7月 5 02:52 a.out -rw-r--r-- 1 atmark atmark 830 7月 5 02:51 test.c ================== ==== count=4 ===== 合計 20 drwxr-xr-x 2 atmark atmark 4096 7月 5 02:52 . drwxr-xr-x 7 atmark atmark 4096 7月 5 02:34 .. -rwxr-xr-x 1 atmark atmark 5888 7月 5 02:52 a.out -rw-r--r-- 1 atmark atmark 830 7月 5 02:51 test.c ==================
// Armadilloではなくて、ATDE6で動かしてます
--
なかむら
sakashita_spc
中村様
お世話になります。
連絡ありがとうございます。
popenのソースを検索すると。
A)https://android.googlesource.com/platform/bionic/+/3884bfe9661955543ce2…
B)https://www.retro11.de/ouxr/211bsd/usr/src/lib/libc/gen/popen.c.html
の2種類があるようで、(A)ソースを利用して、Armadilloで動作させたところ、動作しました。
おそらく、atmark-distのソースは(B)を利用していると、推測します。
(A)はOpenしたfpがリスト構造のバッファに保存されるのですが、(B)ではグローバル変数に保存され、2回目のpopenで1回目が
上書きされてしまっていると思います。
ありがとうございました。
y.nakamura
中村です。
Armadillo-840で実行してみました。
問題ないようです。
> popenのソースを検索すると。
> A)https://android.googlesource.com/platform/bionic/+/3884bfe9661955543ce2…
> B)https://www.retro11.de/ouxr/211bsd/usr/src/lib/libc/gen/popen.c.html
> の2種類があるようで、(A)ソースを利用して、Armadilloで動作させたところ、動作しました。
> おそらく、atmark-distのソースは(B)を利用していると、推測します。
少し長くなりますが、popenのソースについて書いておきます。
atmark-distが使うlibcは、ATDEに入っている
クロスコンパイル済みのglibcです。
これを説明しているところはたくさんありますが、
たとえば・・・
https://users.atmark-techno.com/forum/armadillo/962
| 開発環境(ATDE)にインストールされているビルド済みのライブラリが
| 組み込まれるようになっています。
| (ビルド時にglibcをビルドする必要もありません)
です。
今回のテスト環境は、ちょっと古いのを使っていますが、
- atde5-i386-20161130
- atmark-dist-20170726
- linux-3.4-at23
です。
この環境でビルドしたカーネルとユーザランドを
Armadillo-840に書き込んで、
テストプログラムをarm-linux-gnueabihf-gccしたものを
Armadillo-840に転送して実行しました。
この私の環境で使用されているglibcは、
atmark-distのビルドディレクトリの中をみると、
atmark@atde5:~/work$ cd atmark-dist-20170726/ atmark@atde5:~/work/atmark-dist-20170726$ ls -l romfs/lib/libc* -rwxr-xr-x 1 atmark atmark 905332 9月 26 2017 romfs/lib/libc-2.13.so lrwxrwxrwx 1 atmark atmark 17 9月 26 2017 romfs/lib/libc.so.6 -> /lib/libc-2.13.so lrwxrwxrwx 1 atmark atmark 19 9月 26 2017 romfs/lib/libcap.so.2 -> /lib/libcap.so.2.22 -rw-r--r-- 1 atmark atmark 11028 9月 26 2017 romfs/lib/libcap.so.2.22 lrwxrwxrwx 1 atmark atmark 22 9月 26 2017 romfs/lib/libcom_err.so.2 -> /lib/libcom_err.so.2.1 -rw-r--r-- 1 atmark atmark 9796 9月 26 2017 romfs/lib/libcom_err.so.2.1 -rw-r--r-- 1 atmark atmark 26184 9月 26 2017 romfs/lib/libcrypt-2.13.so lrwxrwxrwx 1 atmark atmark 21 9月 26 2017 romfs/lib/libcrypt.so.1 -> /lib/libcrypt-2.13.so -rw-r--r-- 1 atmark atmark 1127780 9月 26 2017 romfs/lib/libcrypto.so.1.0.0
となっていますので、glibc-2.13が使われていることがわかります。
Armadillo-840にもこれと同じものがインストールされています。
[root@armadillo840-0 (ttySC2) ~]# ls -l /lib/libc* -rwxr-xr-x 2 root root 905332 Sep 26 2017 /lib/libc-2.13.so* lrwxrwxrwx 1 root root 17 Sep 26 2017 /lib/libc.so.6 -> /lib/libc-2.13.so* lrwxrwxrwx 1 root root 19 Sep 26 2017 /lib/libcap.so.2 -> /lib/libcap.so.2.22 -rw-r--r-- 1 root root 11028 Sep 26 2017 /lib/libcap.so.2.22 lrwxrwxrwx 1 root root 22 Sep 26 2017 /lib/libcom_err.so.2 -> /lib/libcom_err.so.2.1 -rw-r--r-- 1 root root 9796 Sep 26 2017 /lib/libcom_err.so.2.1 -rw-r--r-- 1 root root 26184 Sep 26 2017 /lib/libcrypt-2.13.so lrwxrwxrwx 1 root root 21 Sep 26 2017 /lib/libcrypt.so.1 -> /lib/libcrypt-2.13.so -rw-r--r-- 1 root root 1127780 Sep 26 2017 /lib/libcrypto.so.1.0.0
glibc-2.13のソースは、たぶん、
http://ftp.gnu.org/gnu/glibc/
にある glibc-2.13.tar.gz だと思います。
ダウンロードして中をみてみたところ、
たぶん、popenのソースは
glibc-2.13/libio/iopopen.c
だと思います。
先日のテストプログラムは、次のように修正して、
popenしたFILEのfilenoを表示するようにしてみました。
#include <stdio.h> #include <errno.h> int main(int argc, char *argv[]) { int count; FILE *f1, *f2; char buf[1024]; f1 = popen("/bin/ps", "r"); if (f1 == NULL) { perror("popen f1"); return 1; } printf("fileno(f1)=%d\n", fileno(f1)); printf("-----------------------\n"); while (fgets(buf, sizeof buf, f1) != NULL) { printf("%s", buf); } printf("-----------------------\n"); for (count = 0; count < 5; count++) { printf("==== count=%d =====\n", count); f2 = popen("/bin/ls -la", "r"); if (f2 == NULL) { perror("popen f2"); return 1; } printf("fileno(f2)=%d\n", fileno(f2)); while (fgets(buf, sizeof buf, f2) != NULL) { printf("%s", buf); } if (pclose(f2) < 0) { perror("pclose f2"); return 1; } printf("pclose(f2) OK\n"); printf("==================\n"); } if (pclose(f1) < 0) { perror("pclose f1"); return 1; } printf("pclose(f1) OK\n"); return 0; }
--
なかむら
y.nakamura
中村です。
書き忘れがありました。
> atmark-distのビルドディレクトリの中をみると、
> atmark@atde5:~/work$ cd atmark-dist-20170726/
> atmark@atde5:~/work/atmark-dist-20170726$ ls -l romfs/lib/libc*
> -rwxr-xr-x 1 atmark atmark 905332 9月 26 2017 romfs/lib/libc-2.13.so
...
>
> となっていますので、glibc-2.13が使われていることがわかります。
この元になっている(atmark-distのビルドでコピーされる元の)
libc-2.13.soは、ATDEに入っている次のものです。
atmark@atde5:~$ locate libc-2.13.so /home/atmark/work/atmark-dist-20170726/romfs/lib/libc-2.13.so /lib/i386-linux-gnu/libc-2.13.so /lib/i386-linux-gnu/i686/cmov/libc-2.13.so /usr/arm-linux-gnueabi/lib/libc-2.13.so /usr/arm-linux-gnueabihf/lib/libc-2.13.so /usr/lib/debug/lib/i386-linux-gnu/libc-2.13.so /usr/lib/debug/lib/i386-linux-gnu/i686/cmov/libc-2.13.so /usr/lib/debug/lib/i386-linux-gnu/i686/nosegneg/libc-2.13.so atmark@atde5:~$ ls -l /usr/arm-linux-gnueabihf/lib/libc-2.13.so -rwxr-xr-x 1 root root 905332 2月 12 2016 /usr/arm-linux-gnueabihf/lib/libc-2.13.so atmark@atde5:~$ cmp /usr/arm-linux-gnueabihf/lib/libc-2.13.so \ > work/atmark-dist-20170726/romfs/lib/libc-2.13.so (何も表示されないので2つは同じファイル)
--
なかむら
sakashita_spc
sakashita_spc
2019年7月5日 0時42分
サンプルコードをつくてやってみましたが、
*** glibc detected *** ./demo1: double free or corruption (out): 0x00012260 ***
Aborted
のエラーが出てしまいました。(外側のループのpclose()でのエラーですね。)
今回、同一プロセス、同一スレッドでやったのですが、異なるスレッドで
動作すればいいのですが、方法があればお願いします。
以上、よろしくお願いします。