~serge-hallyn/ubuntu/saucy/lxc/lxc-dnsmasq

« back to all changes in this revision

Viewing changes to src/tests/locktests.c

  • Committer: Stéphane Graber
  • Date: 2013-02-18 15:20:18 UTC
  • mto: This revision was merged to the branch mainline in revision 190.
  • Revision ID: stgraber@ubuntu.com-20130218152018-ls2gi9hkqs2kuhj8
Tags: upstream-0.9.0~alpha3
Import upstream version 0.9.0~alpha3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* liblxcapi
 
2
 *
 
3
 * Copyright © 2012 Serge Hallyn <serge.hallyn@ubuntu.com>.
 
4
 * Copyright © 2012 Canonical Ltd.
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License version 2, as
 
8
 * published by the Free Software Foundation.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License along
 
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
18
 */
 
19
#include "../lxc/lxclock.h"
 
20
#include <unistd.h>
 
21
#include <signal.h>
 
22
#include <stdio.h>
 
23
#include <sys/types.h>
 
24
#include <sys/wait.h>
 
25
#include <stdlib.h>
 
26
 
 
27
#define mycontainername "lxctest.sem"
 
28
#define TIMEOUT_SECS 3
 
29
 
 
30
int timedout;
 
31
int pid_to_kill;
 
32
 
 
33
void timeouthandler(int sig)
 
34
{
 
35
        // timeout received
 
36
        timedout = 1;
 
37
        kill(pid_to_kill, SIGTERM);
 
38
}
 
39
 
 
40
void starttimer(int secs)
 
41
{
 
42
        timedout = 0;
 
43
        signal(SIGALRM, timeouthandler);
 
44
        alarm(secs);
 
45
}
 
46
void stoptimer(void)
 
47
{
 
48
        alarm(0);
 
49
        signal(SIGALRM, NULL);
 
50
}
 
51
 
 
52
int test_one_lock(sem_t *lock)
 
53
{
 
54
        int ret;
 
55
        starttimer(TIMEOUT_SECS);
 
56
        ret = lxclock(lock, TIMEOUT_SECS*2);
 
57
        stoptimer();
 
58
        if (ret == 0) {
 
59
                lxcunlock(lock);
 
60
                return 0;
 
61
        }
 
62
        if (timedout)
 
63
                fprintf(stderr, "%d: timed out waiting for lock\n", __LINE__);
 
64
        else
 
65
                fprintf(stderr, "%d: failed to get single lock\n", __LINE__);
 
66
        return 1;
 
67
}
 
68
 
 
69
/*
 
70
 * get one lock.  Fork a second task to try to get a second lock,
 
71
 * with infinite timeout.  If our alarm hits, kill the second
 
72
 * task.  If second task does not
 
73
 */
 
74
int test_two_locks(sem_t *lock)
 
75
{
 
76
        int status;
 
77
    int ret;
 
78
 
 
79
        ret = lxclock(lock, 1);
 
80
        if (ret) {
 
81
                fprintf(stderr, "%d: Error getting first lock\n", __LINE__);
 
82
                return 2;
 
83
        }
 
84
 
 
85
        pid_to_kill = fork();
 
86
        if (pid_to_kill < 0) {
 
87
                fprintf(stderr, "%d: Failed to fork\n", __LINE__);
 
88
                lxcunlock(lock);
 
89
                return 3;
 
90
        }
 
91
 
 
92
        if (pid_to_kill == 0) { // child
 
93
                ret = lxclock(lock, TIMEOUT_SECS*2);
 
94
                if (ret == 0) {
 
95
                        lxcunlock(lock);
 
96
                        exit(0);
 
97
                }
 
98
                fprintf(stderr, "%d: child, was not able to get lock\n", __LINE__);
 
99
                exit(1);
 
100
        }
 
101
        starttimer(TIMEOUT_SECS);
 
102
        waitpid(pid_to_kill, &status, 0);
 
103
        stoptimer();
 
104
        if (WIFEXITED(status)) {
 
105
                // child exited normally - timeout didn't kill it
 
106
                if (WEXITSTATUS(status) == 0)
 
107
                        fprintf(stderr, "%d: child was able to get the lock\n", __LINE__);
 
108
                else
 
109
                        fprintf(stderr, "%d: child timed out too early\n", __LINE__);
 
110
                lxcunlock(lock);
 
111
                return 1;
 
112
        }
 
113
        lxcunlock(lock);
 
114
        return 0;
 
115
}
 
116
 
 
117
/*
 
118
 * get one lock.  try to get second lock, but asking for timeout.  If
 
119
 * should return failure.  If our own alarm, set at twice the lock
 
120
 * request's timeout, hits, then lxclock() did not properly time out.
 
121
 */
 
122
int test_with_timeout(sem_t *lock)
 
123
{
 
124
        int status;
 
125
        int ret = 0;
 
126
 
 
127
        ret = lxclock(lock, 0);
 
128
        if (ret) {
 
129
                fprintf(stderr, "%d: Error getting first lock\n", __LINE__);
 
130
                return 2;
 
131
        }
 
132
        pid_to_kill = fork();
 
133
        if (pid_to_kill < 0) {
 
134
                fprintf(stderr, "%d: Error on fork\n", __LINE__);
 
135
                lxcunlock(lock);
 
136
                return 2;
 
137
        }
 
138
        if (pid_to_kill == 0) {
 
139
                ret = lxclock(lock, TIMEOUT_SECS);
 
140
                if (ret == 0) {
 
141
                        lxcunlock(lock);
 
142
                        exit(0);
 
143
                }
 
144
                exit(1);
 
145
        }
 
146
        starttimer(TIMEOUT_SECS * 2);
 
147
        waitpid(pid_to_kill, &status, 0);
 
148
        stoptimer();
 
149
        if (!WIFEXITED(status)) {
 
150
                fprintf(stderr, "%d: lxclock did not honor its timeout\n", __LINE__);
 
151
                lxcunlock(lock);
 
152
                return 1;
 
153
        }
 
154
        if (WEXITSTATUS(status) == 0) {
 
155
                fprintf(stderr, "%d: child was able to get lock, should have failed with timeout\n", __LINE__);
 
156
                ret = 1;
 
157
        }
 
158
        lxcunlock(lock);
 
159
        return ret;
 
160
}
 
161
 
 
162
int main(int argc, char *argv[])
 
163
{
 
164
        int ret, sval, r;
 
165
        sem_t *lock;
 
166
 
 
167
        lock = lxc_newlock(NULL);
 
168
    if (!lock) {
 
169
                fprintf(stderr, "%d: failed to get unnamed lock\n", __LINE__);
 
170
                exit(1);
 
171
    }
 
172
    ret = lxclock(lock, 0);
 
173
    if (ret) {
 
174
                fprintf(stderr, "%d: failed to take unnamed lock (%d)\n", __LINE__, ret);
 
175
                exit(1);
 
176
    }
 
177
 
 
178
    ret = lxcunlock(lock);
 
179
    if (ret) {
 
180
                fprintf(stderr, "%d: failed to put unnamed lock (%d)\n", __LINE__, ret);
 
181
                exit(1);
 
182
    }
 
183
 
 
184
    sem_destroy(lock);
 
185
    free(lock);
 
186
 
 
187
        lock = lxc_newlock(mycontainername);
 
188
        if (!lock) {
 
189
                fprintf(stderr, "%d: failed to get lock\n", __LINE__);
 
190
                exit(1);
 
191
        }
 
192
        r = sem_getvalue(lock, &sval);
 
193
        if (!r) {
 
194
                fprintf(stderr, "%d: sem value at start is %d\n", __LINE__, sval);
 
195
        } else {
 
196
                fprintf(stderr, "%d: failed to get initial value\n", __LINE__);
 
197
        }
 
198
 
 
199
        ret = test_one_lock(lock);
 
200
        if (ret) {
 
201
                fprintf(stderr, "%d: test failed\n", __LINE__);
 
202
                goto out;
 
203
        }
 
204
        r = sem_getvalue(lock, &sval);
 
205
        if (!r) {
 
206
                fprintf(stderr, "%d: sem value is %d\n", __LINE__, sval);
 
207
        } else {
 
208
                fprintf(stderr, "%d: failed to get sem value\n", __LINE__);
 
209
        }
 
210
 
 
211
        ret = test_two_locks(lock);
 
212
        if (ret) {
 
213
                fprintf(stderr, "%d: test failed\n", __LINE__);
 
214
                goto out;
 
215
        }
 
216
        r = sem_getvalue(lock, &sval);
 
217
        if (!r) {
 
218
                fprintf(stderr, "%d: sem value is %d\n", __LINE__, sval);
 
219
        } else {
 
220
                fprintf(stderr, "%d: failed to get value\n", __LINE__);
 
221
        }
 
222
 
 
223
        ret = test_with_timeout(lock);
 
224
        if (ret) {
 
225
                fprintf(stderr, "%d: test failed\n", __LINE__);
 
226
                goto out;
 
227
        }
 
228
        r = sem_getvalue(lock, &sval);
 
229
        if (!r) {
 
230
                fprintf(stderr, "%d: sem value is %d\n", __LINE__, sval);
 
231
        } else {
 
232
                fprintf(stderr, "%d: failed to get value\n", __LINE__);
 
233
        }
 
234
 
 
235
    fprintf(stderr, "all tests passed\n");
 
236
 
 
237
out:
 
238
        exit(ret);
 
239
}