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 #include <stdio.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <signal.h>
38 #include <stdlib.h>
39 #include <aio.h>
40 #include <time.h>
41
42 #include "posixtest.h"
43 #include "tempfile.h"
44
45 #define TNAME "aio_cancel/3-1.c"
46
47 #define BUF_NB 128
48 #define BUF_SIZE (1024 * 1024)
49
50 static volatile int countdown = BUF_NB;
51 static volatile int canceled;
52
sig_handler(int signum PTS_ATTRIBUTE_UNUSED,siginfo_t * info,void * context PTS_ATTRIBUTE_UNUSED)53 static void sig_handler(int signum PTS_ATTRIBUTE_UNUSED, siginfo_t *info,
54 void *context PTS_ATTRIBUTE_UNUSED)
55 {
56 struct aiocb *a = info->si_value.sival_ptr;
57
58 if (aio_error(a) == ECANCELED)
59 canceled++;
60
61 aio_return(a); /* free entry */
62
63 countdown--;
64 }
65
main(void)66 int main(void)
67 {
68 char tmpfname[PATH_MAX];
69 int fd;
70 struct aiocb *aiocb_list[BUF_NB];
71 struct aiocb *aiocb;
72 struct sigaction action;
73 struct timespec processing_completion_ts = {0, 10000000};
74 int i;
75
76 if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L) {
77 printf(TNAME " %ld\n", sysconf(_SC_ASYNCHRONOUS_IO));
78 return PTS_UNSUPPORTED;
79 }
80
81 PTS_GET_TMP_FILENAME(tmpfname, "pts_aio_cancel_3_1");
82 unlink(tmpfname);
83 fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
84 if (fd == -1) {
85 printf(TNAME " Error at open(): %s\n", strerror(errno));
86 return PTS_UNRESOLVED;
87 }
88
89 unlink(tmpfname);
90
91 /* install signal handler */
92
93 action.sa_sigaction = sig_handler;
94 sigemptyset(&action.sa_mask);
95 action.sa_flags = SA_SIGINFO | SA_RESTART;
96 if (sigaction(SIGRTMIN + 1, &action, NULL)) {
97 printf(TNAME " Error at sigaction(): %s\n", strerror(errno));
98 return PTS_FAIL;
99 }
100
101 /* create AIO req */
102
103 for (i = 0; i < BUF_NB; i++) {
104 aiocb = malloc(sizeof(struct aiocb));
105 if (aiocb == NULL) {
106 printf(TNAME " Error at malloc(): %s\n",
107 strerror(errno));
108 return PTS_FAIL;
109 }
110
111 aiocb->aio_fildes = fd;
112 aiocb->aio_buf = malloc(BUF_SIZE);
113 if (aiocb->aio_buf == NULL) {
114 printf(TNAME " Error at malloc(): %s\n",
115 strerror(errno));
116 return PTS_FAIL;
117 }
118
119 aiocb->aio_nbytes = BUF_SIZE;
120 aiocb->aio_offset = 0;
121
122 aiocb->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
123 aiocb->aio_sigevent.sigev_signo = SIGRTMIN + 1;
124 aiocb->aio_sigevent.sigev_value.sival_ptr = aiocb;
125 aiocb->aio_reqprio = 0;
126
127 aiocb_list[i] = aiocb;
128 }
129
130 for (i = 0; i < BUF_NB; i++) {
131 if (aio_write(aiocb_list[i]) == -1) {
132 printf(TNAME " loop %d: Error at aio_write(): %s\n",
133 i, strerror(errno));
134 return PTS_FAIL;
135 }
136 }
137
138 /* try to cancel all
139 * we hope to have enough time to cancel at least one
140 */
141
142 if (aio_cancel(fd, NULL) == -1) {
143 printf(TNAME " Error at aio_cancel(): %s\n", strerror(errno));
144 return PTS_FAIL;
145 }
146
147 close(fd);
148
149 while (countdown)
150 nanosleep(&processing_completion_ts, NULL);
151
152 if (!canceled)
153 return PTS_UNRESOLVED;
154
155 printf("Test PASSED\n");
156 return PTS_PASS;
157 }
158