test_executable_destructor.c revision 133a37ede3e955093c6004d94496e2cdc2cc1264
1133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner/*
2133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * Copyright (C) 2010 The Android Open Source Project
3133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * All rights reserved.
4133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner *
5133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * Redistribution and use in source and binary forms, with or without
6133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * modification, are permitted provided that the following conditions
7133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * are met:
8133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner *  * Redistributions of source code must retain the above copyright
9133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner *    notice, this list of conditions and the following disclaimer.
10133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner *  * Redistributions in binary form must reproduce the above copyright
11133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner *    notice, this list of conditions and the following disclaimer in
12133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner *    the documentation and/or other materials provided with the
13133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner *    distribution.
14133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner *
15133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * SUCH DAMAGE.
27133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner */
28133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner#include <stdio.h>
29133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner#include <unistd.h>
30133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner#include <errno.h>
31133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner#include <string.h>
32133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner#include <sys/wait.h>
33133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner#include <sys/resource.h>
34133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner
35133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner/* A very simple program used to test constructor and destructor functions
36133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * in executables (instead of shared libraries).
37133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner */
38133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner
39133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turnerint x = 0;
40133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner
41133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner/* Initialize x to 1 when the program starts. This will be checked
42133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner * later by the main() function.
43133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner */
44133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turnerstatic void __attribute__((constructor))
45133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turneron_load(void)
46133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner{
47133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    x = 1;
48133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner}
49133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner
50133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner/* Crash intentionally if 'x' is set to 1 */
51133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turnerstatic void __attribute__((destructor))
52133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turneron_exit(void)
53133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner{
54133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    if (x == 1)
55133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        *(int*)(void*)0 = 10;  /* force a crash */
56133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner}
57133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner
58133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turnerint main(void)
59133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner{
60133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    int status;
61133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    pid_t pid;
62133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner
63133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    /* First, check that the constructor was properly called ! */
64133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    if (x != 1) {
65133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        fprintf(stderr, "Constructor function not called!!\n");
66133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        return 1;
67133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    }
68133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner
69133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    /* prevent our crashing child process from generating a core file */
70133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    {
71133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        struct rlimit rlim;
72133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        rlim.rlim_cur = 0;
73133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        rlim.rlim_max = RLIM_INFINITY;
74133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        setrlimit(RLIMIT_CORE, &rlim);
75133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    }
76133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner
77133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    /* Fork the current process, then wait for the child to exit
78133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner     * and crash.
79133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner     */
80133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    pid = fork();
81133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    if (pid < 0) {
82133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        fprintf(stderr, "Could not fork process: %s\n", strerror(errno));
83133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        return 2;
84133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    }
85133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    /* in the child, simply exit after 1 second. */
86133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    if (pid == 0) {
87133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        sleep(1);
88133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        return 0;
89133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    }
90133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    /* in the parent, wait for the child to terminate */
91133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    if (wait(&status) < 0) {
92133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        fprintf(stderr, "Could not wait for child: %s\n", strerror(errno));
93133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        return 3;
94133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    }
95133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    if (!WIFSIGNALED(status)) {
96133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        fprintf(stderr, "Destructor not called!!\n");
97133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner        return 4;
98133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    }
99133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner
100133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    /* Prevent crashing */
101133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    x = 2;
102133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    printf("ok\n");
103133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner    return 0;
104133a37ede3e955093c6004d94496e2cdc2cc1264David 'Digit' Turner}
105