clone() prototype
Frank Bergmann <[email protected]> Thu, 23 Feb 2012 13:54:30 +0100 (CET)
| Newsgroups | gmane.linux.lib.dietlibc |
|---|---|
| Message-ID | <[email protected]> |
Hi,
the current prototype of clone() as of 2011-12-20 (sched.h) still seems to
be wrong.
Environment is i386, different kernels and gcc.
dietlibc declares the function prototype of the first argument of clone()
as
int *(*fn)(void*)
but actually uses
int (*fn)(void*)
as the following code snippet shows.
$ gcc -Os -Wall -o clonefunctest clonefunctest.c # glibc uses int (*fn)(void *)
$ ./clonefunctest
child_status=123 wait=Success
$ diet -Os gcc -Os -Wall -o clonefunctest clonefunctest.c # still return int and not int*
clonefunctest.c: In function ?measure?:
clonefunctest.c:24: warning: return makes pointer from integer without a cast
/opt/diet/lib-i386/libc.a(vprintf.o): In function `vprintf':
vprintf.c:(.text+0x20): warning: warning: the printf functions add several kilobytes of bloat.
$ ./clonefunctest
child_status=123 wait=Success
$ diet -Os gcc -Os -Wall -o clonefunctest2 clonefunctest2.c # return int* as declared in sched.h
/opt/diet/lib-i386/libc.a(vprintf.o): In function `vprintf':
vprintf.c:(.text+0x20): warning: warning: the printf functions add several kilobytes of bloat.
$ ./clonefunctest2
child_status=64 wait=Success
Here the "thread" returns with int* (actually pointer to 123) but the
status is the low byte of the (aligned) address.
$ diff -u clonefunctest.c clonefunctest2.c
--- clonefunctest.c 2012-02-23 13:16:39.000000000 +0100
+++ clonefunctest2.c 2012-02-23 13:16:54.000000000 +0100
@@ -21,7 +21,8 @@
/* int clone(int (*fn)(void *) */
int measure(void *notused) {
#endif
- return 123;
+ *pglobalint = 123;
+ return pglobalint;
}
int main(int argc, char *argv[]) {
$ cat clonefunctest.c
#define _GNU_SOURCE
#include <features.h>
#include <stdint.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sched.h>
#define STACKSIZE 4096
static char stack[STACKSIZE];
static int globalint;
static int *pglobalint;
#ifdef __dietlibc__
/* /opt/diet/include/sched.h:int clone(int *(*fn)(void*),void* stack,int flags,void* arg, ...); */
int *measure(void *notused) {
#else
/* int clone(int (*fn)(void *) */
int measure(void *notused) {
#endif
return 123;
}
int main(int argc, char *argv[]) {
char *child_stack;
uint32_t flags;
int child_status;
pglobalint = &globalint;
globalint = 0;
child_status = -1;
child_stack = stack + STACKSIZE;
flags =
CLONE_FILES |
CLONE_FS |
CLONE_VM;
clone(measure, child_stack, flags, 0);
/* NOTE: dietlibc defines 'int *(*)(void *)' but glibc defines 'int (*)(void *)' as first arg */
waitpid(-1, &child_status, __WALL);
printf("child_status=%d wait=%s\n", WEXITSTATUS(child_status), strerror(errno));
return 0;
}
Frank
--
EDV Frank Bergmann Tel. 05221-9249753
LPIC-3 Linux Professional Fax 05221-9249754
Pödinghauser Str. 5 email [email protected]
32051 Herford USt-IdNr DE237314606