1/*
2 * Copyright (c) 2004, Bull SA. All rights reserved.
3 * Created by:  Laurent.Vivier@bull.net
4 * This file is licensed under the GPL license.  For the full content
5 * of this license, see the COPYING file at the top level of this
6 * source tree.
7 */
8
9/*
10 * assertion:
11 *
12 *	Asynchronous notification shall occur for AIO that are successfully
13 *	cancelled.
14 *
15 * method:
16 *
17 *	we queue a lot of aio_write() with a valid sigevent to a file descriptor
18 *	next we try to cancel all operations on this file descriptor
19 *	we guess some have been finished, other are in progress,
20 *	other are waiting
21 *	we guess we can cancel all operations waiting
22 *	then we analyze aio_error() in the event handler
23 *	if aio_error() is ECANCELED, the test is passed
24 *	otherwise, we don't know (perhaps we haven't cancel any operation ?)
25 *	if number of sig event is not equal to number of aio_write()
26 *	the test fails (in fact it hangs).
27 *
28 */
29
30#define _XOPEN_SOURCE 600
31#include <stdio.h>
32#include <sys/types.h>
33#include <unistd.h>
34#include <sys/stat.h>
35#include <fcntl.h>
36#include <string.h>
37#include <errno.h>
38#include <stdlib.h>
39#include <malloc.h>
40#include <aio.h>
41
42#include "posixtest.h"
43
44#define TNAME "aio_cancel/3-1.c"
45
46#define BUF_NB		128
47#define BUF_SIZE	1024
48
49static volatile int countdown = BUF_NB;
50static volatile int canceled = 0;
51
52void sigusr1_handler(int signum, siginfo_t *info, void *context)
53{
54	struct aiocb *a = info->si_value.sival_ptr;
55
56	if (aio_error(a) == ECANCELED)
57		canceled++;
58
59	aio_return(a);	/* free entry */
60
61	free((void*)a->aio_buf);
62	free(a);
63
64	countdown--;
65}
66
67int main()
68{
69	char tmpfname[256];
70	int fd;
71	struct aiocb *aiocb;
72	struct sigaction action;
73	int i;
74
75#if _POSIX_ASYNCHRONOUS_IO != 200112L
76	return PTS_UNSUPPORTED;
77#endif
78
79	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_cancel_3_1_%d",
80		  getpid());
81	unlink(tmpfname);
82	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
83	if (fd == -1)
84	{
85		printf(TNAME " Error at open(): %s\n",
86		       strerror(errno));
87		return PTS_UNRESOLVED;
88	}
89
90	unlink(tmpfname);
91
92	/* install signal handler */
93
94	action.sa_sigaction = sigusr1_handler;
95	sigemptyset(&action.sa_mask);
96	action.sa_flags = SA_SIGINFO|SA_RESTART;
97	if (sigaction(SIGRTMIN+1, &action, NULL))
98	{
99		printf(TNAME " Error at sigaction(): %s\n",
100		       strerror(errno));
101		return PTS_FAIL;
102	}
103
104	/* create AIO req */
105
106	for (i = 0; i < BUF_NB; i++)
107	{
108		aiocb = malloc(sizeof(struct aiocb));
109		if (aiocb == NULL)
110		{
111			printf(TNAME " Error at malloc(): %s\n",
112		       		strerror(errno));
113			return PTS_FAIL;
114		}
115
116		aiocb->aio_fildes = fd;
117		aiocb->aio_buf = malloc(BUF_SIZE);
118		if (aiocb->aio_buf == NULL)
119		{
120			printf(TNAME " Error at malloc(): %s\n",
121		       		strerror(errno));
122			return PTS_FAIL;
123		}
124
125		aiocb->aio_nbytes = BUF_SIZE;
126		aiocb->aio_offset = 0;
127
128		aiocb->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
129		aiocb->aio_sigevent.sigev_signo = SIGRTMIN+1;
130		aiocb->aio_sigevent.sigev_value.sival_ptr = aiocb;
131
132		if (aio_write(aiocb) == -1)
133		{
134			printf(TNAME " loop %d: Error at aio_write(): %s\n",
135			       i, strerror(errno));
136			return PTS_FAIL;
137		}
138	}
139
140	/* try to cancel all
141	 * we hope to have enough time to cancel at least one
142	 */
143
144	if (aio_cancel(fd, NULL) == -1)
145	{
146		printf(TNAME " Error at aio_cancel(): %s\n",
147		       strerror(errno));
148		return PTS_FAIL;
149	}
150
151	close(fd);
152
153	while(countdown);
154
155	if (!canceled)
156		return PTS_UNRESOLVED;
157
158	printf ("Test PASSED\n");
159	return PTS_PASS;
160}
161