aboutsummaryrefslogtreecommitdiff
path: root/testcases/open_posix_testsuite/conformance/interfaces/aio_cancel/3-1.c
blob: 0842edd0f936fa347505ff41446142cc4b5d1245 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
 * Copyright (c) 2004, Bull SA. All rights reserved.
 * Created by:  Laurent.Vivier@bull.net
 * This file is licensed under the GPL license.  For the full content
 * of this license, see the COPYING file at the top level of this
 * source tree.
 */

/*
 * assertion:
 *
 *	Asynchronous notification shall occur for AIO that are successfully
 *	cancelled.
 *
 * method:
 *
 *	we queue a lot of aio_write() with a valid sigevent to a file descriptor
 *	next we try to cancel all operations on this file descriptor
 *	we guess some have been finished, other are in progress,
 *	other are waiting
 *	we guess we can cancel all operations waiting
 *	then we analyze aio_error() in the event handler
 *	if aio_error() is ECANCELED, the test is passed
 *	otherwise, we don't know (perhaps we haven't cancel any operation ?)
 *	if number of sig event is not equal to number of aio_write()
 *	the test fails (in fact it hangs).
 *
 */

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <aio.h>
#include <time.h>

#include "posixtest.h"

#define TNAME "aio_cancel/3-1.c"

#define BUF_NB		128
#define BUF_SIZE	(1024 * 1024)

static volatile int countdown = BUF_NB;
static volatile int canceled;

void sig_handler(int signum, siginfo_t *info, void *context)
{
	struct aiocb *a = info->si_value.sival_ptr;

	if (aio_error(a) == ECANCELED)
		canceled++;

	aio_return(a);		/* free entry */

	countdown--;
}

int main(void)
{
	char tmpfname[256];
	int fd;
	struct aiocb *aiocb_list[BUF_NB];
	struct aiocb *aiocb;
	struct sigaction action;
	struct timespec processing_completion_ts = {0, 10000000};
	int i;

	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L) {
		printf(TNAME " %ld\n", sysconf(_SC_ASYNCHRONOUS_IO));
		return PTS_UNSUPPORTED;
	}

	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_cancel_3_1_%d",
		 getpid());
	unlink(tmpfname);
	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
	if (fd == -1) {
		printf(TNAME " Error at open(): %s\n", strerror(errno));
		return PTS_UNRESOLVED;
	}

	unlink(tmpfname);

	/* install signal handler */

	action.sa_sigaction = sig_handler;
	sigemptyset(&action.sa_mask);
	action.sa_flags = SA_SIGINFO | SA_RESTART;
	if (sigaction(SIGRTMIN + 1, &action, NULL)) {
		printf(TNAME " Error at sigaction(): %s\n", strerror(errno));
		return PTS_FAIL;
	}

	/* create AIO req */

	for (i = 0; i < BUF_NB; i++) {
		aiocb = malloc(sizeof(struct aiocb));
		if (aiocb == NULL) {
			printf(TNAME " Error at malloc(): %s\n",
			       strerror(errno));
			return PTS_FAIL;
		}

		aiocb->aio_fildes = fd;
		aiocb->aio_buf = malloc(BUF_SIZE);
		if (aiocb->aio_buf == NULL) {
			printf(TNAME " Error at malloc(): %s\n",
			       strerror(errno));
			return PTS_FAIL;
		}

		aiocb->aio_nbytes = BUF_SIZE;
		aiocb->aio_offset = 0;

		aiocb->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
		aiocb->aio_sigevent.sigev_signo = SIGRTMIN + 1;
		aiocb->aio_sigevent.sigev_value.sival_ptr = aiocb;
		aiocb->aio_reqprio = 0;

		aiocb_list[i] = aiocb;
	}

	for (i = 0; i < BUF_NB; i++) {
		if (aio_write(aiocb_list[i]) == -1) {
			printf(TNAME " loop %d: Error at aio_write(): %s\n",
			       i, strerror(errno));
			return PTS_FAIL;
		}
	}

	/* try to cancel all
	 * we hope to have enough time to cancel at least one
	 */

	if (aio_cancel(fd, NULL) == -1) {
		printf(TNAME " Error at aio_cancel(): %s\n", strerror(errno));
		return PTS_FAIL;
	}

	close(fd);

	while (countdown)
		nanosleep(&processing_completion_ts, NULL);

	if (!canceled)
		return PTS_UNRESOLVED;

	printf("Test PASSED\n");
	return PTS_PASS;
}