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
44 #define TNAME "aio_cancel/3-1.c"
45
46 #define BUF_NB 128
47 #define BUF_SIZE (1024 * 1024)
48
49 static volatile int countdown = BUF_NB;
50 static volatile int canceled;
51
sig_handler(int signum LTP_ATTRIBUTE_UNUSED,siginfo_t * info,void * context LTP_ATTRIBUTE_UNUSED)52 void sig_handler(int signum LTP_ATTRIBUTE_UNUSED, siginfo_t *info,
53 void *context LTP_ATTRIBUTE_UNUSED)
54 {
55 struct aiocb *a = info->si_value.sival_ptr;
56
57 if (aio_error(a) == ECANCELED)
58 canceled++;
59
60 aio_return(a); /* free entry */
61
62 countdown--;
63 }
64
main(void)65 int main(void)
66 {
67 char tmpfname[256];
68 int fd;
69 struct aiocb *aiocb_list[BUF_NB];
70 struct aiocb *aiocb;
71 struct sigaction action;
72 struct timespec processing_completion_ts = {0, 10000000};
73 int i;
74
75 if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L) {
76 printf(TNAME " %ld\n", sysconf(_SC_ASYNCHRONOUS_IO));
77 return PTS_UNSUPPORTED;
78 }
79
80 snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_cancel_3_1_%d",
81 getpid());
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