2 //=============================================================================
4 * @file test_aiosig_ace.cpp
6 * This program helps you to test the <aio_*> calls on a
8 * Before running this test, make sure the platform can
9 * support POSIX <aio_> calls, using ACE_ROOT/tests/Aio_Plaform_Test.cpp
10 * This program tests the Signal based completion approach which
11 * uses <sigtimedwait> for completion querying.
12 * If this test is successful, ACE_POSIX_SIG_PROACTOR
13 * can be used on this platform.
14 * This program is a ACE version of the
15 * $ACE_ROOT/examples/Reactor/Proactor/test_aiosig.cpp, with
16 * ACE_DEBUGs and Message_Blocks.
17 * This test does the following:
18 * Issue two <aio_read>s.
19 * Assign SIGRTMIN as the notification signal.
20 * Mask these signals from delivery.
21 * Receive this signal by doing <sigtimedwait>.
22 * Wait for two completions (two signals)
25 * @author Programming for the Real World. Bill O. GallMeister. Modified by Alexander Babu Arulanthu <alex@cs.wustl.edu>
27 //=============================================================================
30 #include "ace/Message_Block.h"
31 #include "ace/Log_Msg.h"
32 #include "ace/os_include/os_aio.h"
33 #include "ace/OS_NS_signal.h"
34 #include "ace/OS_NS_unistd.h"
35 #include "ace/OS_NS_fcntl.h"
36 #include "ace/Asynch_IO.h" // for ACE_INFINITE
38 static ACE_HANDLE file_handle
= ACE_INVALID_HANDLE
;
39 static ACE_Message_Block
mb1 (BUFSIZ
+ 1);
40 static ACE_Message_Block
mb2 (BUFSIZ
+ 1);
44 static sigset_t completion_signal
;
46 // Function prototypes.
47 static int setup_signal_delivery ();
48 static int issue_aio_calls ();
49 static int query_aio_completions ();
50 static int test_aio_calls ();
51 static void null_handler (int signal_number
, siginfo_t
*info
, void *context
);
52 static int setup_signal_handler (int signal_number
);
55 setup_signal_delivery ()
57 // = Mask all the signals.
62 if (ACE_OS::sigfillset (&full_set
) != 0)
63 ACE_ERROR_RETURN ((LM_ERROR
,
64 "Error:(%P | %t):%p\n",
69 if (ACE_OS::pthread_sigmask (SIG_SETMASK
, &full_set
, 0) != 0)
70 ACE_ERROR_RETURN ((LM_ERROR
,
71 "Error:(%P | %t):%p\n",
72 "pthread_sigmask failed"),
75 // = Make a mask with SIGRTMIN only. We use only that signal to
78 if (ACE_OS::sigemptyset (&completion_signal
) == -1)
79 ACE_ERROR_RETURN ((LM_ERROR
, "Error: %p\n",
80 "Couldnt init the RT completion signal set"),
83 if (ACE_OS::sigaddset (&completion_signal
,
85 ACE_ERROR_RETURN ((LM_ERROR
, "Error: %p\n",
86 "Couldnt init the RT completion signal set"),
89 // Set up signal handler for this signal.
90 return setup_signal_handler (SIGRTMIN
);
94 setup_signal_handler (int signal_number
)
96 ACE_UNUSED_ARG (signal_number
);
98 // Setting up the handler(!) for these signals.
99 struct sigaction reaction
;
100 ACE_OS::sigemptyset (&reaction
.sa_mask
); // Nothing else to mask.
101 reaction
.sa_flags
= SA_SIGINFO
; // Realtime flag.
102 #if defined (SA_SIGACTION)
103 // Lynx says, it is better to set this bit to be portable.
104 reaction
.sa_flags
&= SA_SIGACTION
;
105 #endif /* SA_SIGACTION */
106 reaction
.sa_sigaction
= null_handler
; // Null handler.
107 int sigaction_return
= ACE_OS::sigaction (SIGRTMIN
,
110 if (sigaction_return
== -1)
111 ACE_ERROR_RETURN ((LM_ERROR
, "Error: %p\n",
112 "Proactor couldnt do sigaction for the RT SIGNAL"),
122 aiocb1
.aio_fildes
= file_handle
;
123 aiocb1
.aio_offset
= 0;
124 aiocb1
.aio_buf
= mb1
.wr_ptr ();
125 aiocb1
.aio_nbytes
= BUFSIZ
;
126 aiocb1
.aio_reqprio
= 0;
127 aiocb1
.aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
128 aiocb1
.aio_sigevent
.sigev_signo
= SIGRTMIN
;
129 aiocb1
.aio_sigevent
.sigev_value
.sival_ptr
= (void *) &aiocb1
;
131 // Fire off the aio read.
132 if (aio_read (&aiocb1
) == -1)
134 ACE_ERROR_RETURN ((LM_ERROR
, "Error: %p\n",
135 "Asynch_Read_Stream: aio_read queueing failed"),
139 aiocb2
.aio_fildes
= file_handle
;
140 aiocb2
.aio_offset
= BUFSIZ
+ 1;
141 aiocb2
.aio_buf
= mb2
.wr_ptr ();
142 aiocb2
.aio_nbytes
= BUFSIZ
;
143 aiocb2
.aio_reqprio
= 0;
144 aiocb2
.aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
145 aiocb2
.aio_sigevent
.sigev_signo
= SIGRTMIN
;
146 aiocb2
.aio_sigevent
.sigev_value
.sival_ptr
= (void *) &aiocb2
;
148 // Fire off the aio read.
149 if (aio_read (&aiocb2
) == -1)
151 ACE_ERROR_RETURN ((LM_ERROR
, "Error: %p\n",
152 "Asynch_Read_Stream: aio_read queueing failed"),
156 aiocb3
.aio_fildes
= ACE_INVALID_HANDLE
;
157 aiocb3
.aio_offset
= 0;
159 aiocb3
.aio_nbytes
= 0;
160 aiocb3
.aio_reqprio
= 0;
161 aiocb3
.aio_sigevent
.sigev_notify
= SIGEV_SIGNAL
;
162 aiocb3
.aio_sigevent
.sigev_signo
= SIGRTMIN
;
163 aiocb3
.aio_sigevent
.sigev_value
.sival_ptr
= (void *) &aiocb3
;
165 value
.sival_ptr
= reinterpret_cast<void *> (&aiocb3
);
166 // Queue this one for completion right now.
167 if (sigqueue (ACE_OS::getpid (), SIGRTMIN
, value
) == -1)
169 ACE_ERROR_RETURN ((LM_ERROR
,
170 "Error: %p\n", "sigqueue"),
177 query_aio_completions ()
179 for (size_t number_of_compleions
= 0;
180 number_of_compleions
< 3;
181 number_of_compleions
++)
183 // Wait for <milli_seconds> amount of time. @@ Assigning
184 // <milli_seconds> to tv_sec.
186 timeout
.tv_sec
= ACE_INFINITE
;
189 // To get back the signal info.
192 // Await the RT completion signal.
193 int sig_return
= ACE_OS::sigtimedwait (&completion_signal
,
198 // If failure is coz of timeout, then return *0* but set
199 // errno appropriately. This is what the WinNT proactor
201 if (sig_return
== -1)
202 ACE_ERROR_RETURN ((LM_ERROR
, "Error: %p\n",
203 "Error waiting for RT completion signals"),
206 //FUZZ: disable check_for_lack_ACE_OS
207 // RT completion signals returned.
208 if (sig_return
!= SIGRTMIN
)
209 ACE_ERROR_RETURN ((LM_ERROR
,
210 "Unexpected signal (%d) has been received while waiting for RT Completion Signals\n",
213 //FUZZ: enble check_for_lack_ACE_OS
216 ACE_DEBUG ((LM_DEBUG
,
217 "Sig number found in the sig_info block : %d\n",
220 // Is the signo returned consistent?
221 if (sig_info
.si_signo
!= sig_return
)
222 ACE_ERROR_RETURN ((LM_ERROR
,
223 "Inconsistent signal number (%d) in the signal info block\n",
228 ACE_DEBUG ((LM_DEBUG
,
229 "Signal code for this signal delivery : %d\n",
232 // Is the signal code an aio completion one?
233 if ((sig_info
.si_code
!= SI_ASYNCIO
) &&
234 (sig_info
.si_code
!= SI_QUEUE
))
235 ACE_ERROR_RETURN ((LM_DEBUG
,
236 "Unexpected signal code (%d) returned on completion querying\n",
240 // Retrive the aiocb.
241 aiocb
* aiocb_ptr
= (aiocb
*) sig_info
.si_value
.sival_ptr
;
242 if (aiocb_ptr
== &aiocb3
)
244 ACE_ASSERT (sig_info
.si_code
== SI_QUEUE
);
245 ACE_DEBUG ((LM_DEBUG
, "sigqueue caught... good\n"));
249 // Analyze error and return values. Return values are
250 // actually <errno>'s associated with the <aio_> call
251 // corresponding to aiocb_ptr.
252 int error_code
= aio_error (aiocb_ptr
);
253 if (error_code
== -1)
254 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n",
255 "Invalid control block was sent to <aio_error> for completion querying"),
259 // Error occurred in the <aio_>call. Return the errno
260 // corresponding to that <aio_> call.
261 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n",
262 "An AIO call has failed"),
265 // No error occurred in the AIO operation.
266 int nbytes
= aio_return (aiocb_ptr
);
268 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n",
269 "Invalid control block was send to <aio_return>"),
271 if (number_of_compleions
== 0)
274 ACE_DEBUG ((LM_DEBUG
,
275 "\n Number of bytes transferred : %d\n",
277 // Note... the dumps of the buffers are disabled because they
278 // may easily overrun the ACE_Log_Msg output buffer. If you need
279 // to turn the on for some reason, be careful of this.
281 ACE_DEBUG ((LM_DEBUG
, "The buffer : %s\n", mb1
.rd_ptr ()));
287 ACE_DEBUG ((LM_DEBUG
,
288 "\n Number of bytes transferred : %d\n",
291 ACE_DEBUG ((LM_DEBUG
, "The buffer : %s\n", mb2
.rd_ptr ()));
303 // Set up the input file.
304 // Open file (in SEQUENTIAL_SCAN mode)
305 file_handle
= ACE_OS::open ("test_aiosig_ace.cpp",
308 if (file_handle
== ACE_INVALID_HANDLE
)
309 ACE_ERROR_RETURN ((LM_ERROR
,
314 if (setup_signal_delivery () == -1)
317 if (issue_aio_calls () == -1)
320 if (query_aio_completions () == -1)
327 null_handler (int signal_number
,
328 siginfo_t */
* info */
,
329 void * /* context */)
331 ACE_ERROR ((LM_ERROR
,
332 "Error:%s:Signal number %d\n"
333 "Mask all the RT signals for this thread",
334 "ACE_POSIX_SIG_Proactor::null_handler called",
339 ACE_TMAIN (int, ACE_TCHAR
*[])
341 if (test_aio_calls () == 0)
342 ACE_OS::printf ("RT SIG test successful:\n"
343 "ACE_POSIX_SIG_PROACTOR should work in this platform\n");
345 ACE_OS::printf ("RT SIG test failed:\n"
346 "ACE_POSIX_SIG_PROACTOR may not work in this platform\n");