[BUG] syscall wipes pthread's thread internal info, broking pthread_cancel and other funcs
Hello!
I've found a bug in GNU libc-2.3.2 on Linux - i386 platform. I'm trying to
work with threads, sometimes it is needed to quickly (without reaching a
cancellation point) stop a thread. I've used pthread_cancel function but it
doesn't work in the following example:
#include <pthread.h>
#include <unistd.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
void* bug (void *t)
{
int fd;
int a;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
fd = open("/dev/zero", O_RDONLY);
printf("opened fd = %d\n", fd);
close(fd);
while (1) {
a++;
}
}
int main()
{
pthread_t th;
int retval;
pthread_create(&th, 0, bug, 0);
usleep(100000);
pthread_cancel(th);
pthread_join(th, &retval);
}
Further investigations shows that close() function is written as assembly
macro, defined in linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h.
If pthread is available, macro defines to the following:
CENABLE
SAVE_OLDTYPE_##args
PUSHARGS_##args
DOCARGS_##args
movl $SYS_ify (syscall_name), %eax;
int $0x80
POPARGS_##args;
POPCARGS_##args
cmpl $-4095, %eax;
jae SYSCALL_ERROR_LABEL
If syscall has one paramers (as in case of close), value returned from CENABLE
(which is defined to call __pthread_enable_asynccancel) will be overwritten
in the next statements. This result in calling __pthread_disable_asynccancel
call with wrong parameters. All this things broke cancel handling in thread
structure, preventing pthread_cancel from work.
My system:
[alex@lorien alex]$ dpkg -l |grep libc6
ii libc6 2.3.2-9 GNU C Library: Shared libraries and Timezone
ii libc6-dbg 2.3.2-9 GNU C Library: Libraries with debugging symb
ii libc6-dev 2.3.2-9 GNU C Library: Development Libraries and Hea
With best regards,
Alexander Vodomerov.
Reply to: