From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-3.3 required=5.0 tests=MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 28569 invoked from network); 25 Jun 2022 12:51:25 -0000 Received: from mother.openwall.net (195.42.179.200) by inbox.vuxu.org with ESMTPUTF8; 25 Jun 2022 12:51:25 -0000 Received: (qmail 17680 invoked by uid 550); 25 Jun 2022 12:51:23 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: musl@lists.openwall.com Received: (qmail 17648 invoked from network); 25 Jun 2022 12:51:22 -0000 Date: Sat, 25 Jun 2022 14:51:10 +0200 From: Szabolcs Nagy To: Nick Peng Cc: musl@lists.openwall.com Message-ID: <20220625125110.GV1320090@port70.net> Mail-Followup-To: Nick Peng , musl@lists.openwall.com References: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable In-Reply-To: Subject: Re: [musl] BUG: Calling readdir/dirfd after vfork will cause deadlock. * Nick Peng [2022-06-25 11:40:17 +0800]: > Description: After vfork, calling functions such as readdir/dirfd may > cause deadlock. GNU C is OK. why do you think "GNU C is OK"? is this from some real software? opendir after vfork is documented to be invalid in glibc: https://www.gnu.org/software/libc/manual/html_mono/libc.html#Low_002dlevel-= Directory-Access the standard is actually much stricter than the glibc manual: posix conforming code must not call any libc api after vfork other than _exit or the exec* familiy of functions. (as-safe is not enough, but opendir is not even as-safe) since the example is multi-threaded even using fork would be invalid, but i think both musl and glibc makes that work (as an extension to the standard). > Also tested on x86-64 with musl, no deadlock, but > seems never exit, slower than GNU C. > Version: latest, musl-1.2.3 > OS: debian bullseye 64bit OS. and asus router > CPU: raspberrypi aarch64=EF=BC=8C mips32 > Reproduce Code: >=20 > #include > #include > #include > #include > #include > #include > #include > #include > #include >=20 > pthread_mutex_t lock =3D PTHREAD_MUTEX_INITIALIZER; > pthread_cond_t cond =3D PTHREAD_COND_INITIALIZER; >=20 > struct tlog_log *logs =3D NULL; > int do_exit =3D 0; >=20 > void *test(void *arg) > { > int i =3D 0; >=20 > for (i =3D 0; i < 10000000; i++) { > char *b =3D malloc(4096); > memset(b, 0, 4096); > free(b); > } > do_exit =3D 1; > return NULL; > } >=20 > void lockfunc() > { > char path_name[4096]; > DIR *dir =3D NULL; > struct dirent *ent; >=20 > snprintf(path_name, sizeof(path_name), "/proc/self/fd/"); > dir =3D opendir(path_name); > if (dir =3D=3D NULL) { > goto errout; > } >=20 > while ((ent =3D readdir(dir)) !=3D NULL) { > } >=20 > closedir(dir); >=20 > return; > errout: > if (dir) { > closedir(dir); > } >=20 > return; > } >=20 > void *test_fork(void *arg) > { > int count =3D 0; > while (do_exit =3D=3D 0) { > printf("test fork count %d\n", count++); > int pid =3D vfork(); > if (pid < 0) { > return NULL; > } else if (pid =3D=3D 0) { > lockfunc(); > _exit(0); > } >=20 > int status; > waitpid(pid, &status, 0); > } >=20 > return NULL; > } >=20 > int main(int argc, char *argv[]) > { > pthread_attr_t attr; > pthread_t threads[10]; > pthread_t fork_test; > int i; > int ret; >=20 > pthread_attr_init(&attr); >=20 > ret =3D pthread_create(&fork_test, &attr, test_fork, NULL); >=20 > for (i =3D 0; i < 10; i++) { > ret =3D pthread_create(&threads[i], &attr, test, NULL); > if (ret !=3D 0) { > return 1; > } > } >=20 > for (i =3D 0; i < 10; i++) { > void *retval =3D NULL; > pthread_join(threads[i], &retval); > } >=20 > void *retval =3D NULL; > pthread_join(fork_test, &retval); > printf("exit\n"); > getchar(); > return 0; > } >=20 >=20 > Log=EF=BC=9A > pi@raspberrypi:~/code/tinylog/test $ ./test > test fork count 0 > test fork count 1 <-- lock here > ^C >=20 > gdb backtrace: > x0000000000409524 in __lock () > (gdb) bt > #0 0x0000000000409524 in __lock () > #1 0x0000000000406278 in __libc_malloc_impl ()