55#include <string.h>
66#include <fcntl.h>
77#include <errno.h>
8+ #include <unistd.h>
89
910typedef struct py_aio_callback {
1011 struct aiocb * cb ;
@@ -18,93 +19,61 @@ PyDoc_STRVAR(pyaio_read_doc,
1819PyDoc_STRVAR (pyaio_write_doc ,
1920 "aio_write(fileno, buffer, offset, callback)\n" );
2021
21- static void aio_read_completion_handler ( int sig , siginfo_t * info , void * context )
22+ static int _async_callback ( void * arg )
2223{
23- Pyaio_cb * aio ;
24+ Pyaio_cb * aio = ( Pyaio_cb * ) arg ;
2425 struct aiocb * cb ;
25- PyObject * callback , * args ;
26+ PyObject * callback , * args , * result , * buffer ;
2627 Py_ssize_t read_size = 0 ;
2728 Py_buffer pbuf ;
2829
29- PyGILState_STATE gstate ;
30- gstate = PyGILState_Ensure ();
31-
32- aio = (Pyaio_cb * ) info -> si_value .sival_ptr ;
33-
3430 cb = aio -> cb ;
3531 callback = aio -> callback ;
32+ buffer = aio -> buffer ;
3633
37- /* Lets only let python know about how much was actually read */
38- if (aio_return (cb ) > 0 ) {
39- read_size = aio_return (cb );
34+ if (buffer == NULL ) {
35+ if (aio_return (cb ) > 0 ) {
36+ read_size = aio_return (cb );
37+ }
38+ /* Create a return buffer */
39+ PyBuffer_FillInfo (& pbuf , 0 , (void * )cb -> aio_buf , read_size , 0 ,
40+ PyBUF_CONTIG );
41+ args = Py_BuildValue ("(Nni)" , PyMemoryView_FromBuffer (& pbuf ),
42+ aio_return (cb ), aio_error (cb ));
43+ }
44+ else { /* WRITE */
45+ args = Py_BuildValue ("(ni)" , aio_return (cb ), aio_error (cb ));
4046 }
41-
42- /* Create a buffer to return the data to python */
43- PyBuffer_FillInfo (& pbuf , 0 , (void * )cb -> aio_buf , read_size , 0 , PyBUF_CONTIG );
44-
45- args = Py_BuildValue ("(Nni)" , PyMemoryView_FromBuffer (& pbuf ),
46- aio_return (cb ), aio_error (cb ));
47-
4847 Py_XINCREF (args );
49-
50- //TODO add checking for null, kill program
51- PyObject_CallObject (callback , args );
52-
48+ result = PyObject_CallObject (callback , args );
49+ if (result == NULL ) {
50+ printf ("Exception in aio callback, dying!\n" );
51+ kill (getpid (), SIGKILL ); // DIE FAST
52+ }
53+ Py_XDECREF (result );
5354 Py_XDECREF (callback );
5455 Py_XDECREF (args );
55-
56+ if (buffer != NULL ) {
57+ Py_XDECREF (buffer );
58+ }
5659 free ((struct aiocb * )cb );
5760 free (aio );
58-
59- PyGILState_Release (gstate );
61+ return 0 ;
6062}
6163
62- static void aio_write_completion_handler ( int sig , siginfo_t * info , void * context )
64+ static void aio_completion_handler ( sigval_t sigval )
6365{
6466 Pyaio_cb * aio ;
65- struct aiocb * cb ;
66- PyObject * callback , * args ;
67-
68- PyGILState_STATE gstate ;
69- gstate = PyGILState_Ensure ();
70-
71- aio = (Pyaio_cb * ) info -> si_value .sival_ptr ;
72- cb = aio -> cb ;
73- callback = aio -> callback ;
74- args = Py_BuildValue ("(ni)" , aio_return (cb ), aio_error (cb ));
75-
76- Py_XDECREF (aio -> buffer );
77- Py_XINCREF (args );
78-
79- //TODO add checking for return null, kill program
80- PyObject_CallObject (callback , args );
81-
82- Py_XDECREF (callback );
83- Py_XDECREF (args );
67+ int tries = 1 ;
68+ aio = (Pyaio_cb * ) sigval .sival_ptr ;
8469
85- free (( struct aiocb * ) cb );
86- free ( aio );
87-
88- PyGILState_Release ( gstate ) ;
89- }
70+ //We should set an upper limit like 50 retries or something
71+ while ( Py_AddPendingCall ( & _async_callback , aio ) < 0 ) {
72+ usleep ( 500 * ( tries / 2 )); //Step off timer
73+ tries += 1 ;
74+ }
9075
91- static void init_sig_handlers (void )
92- {
93- struct sigaction * sa ;
94-
95- /* Install Read Handler */
96- sa = malloc (sizeof (struct sigaction ));
97- sigemptyset (& sa -> sa_mask );
98- sa -> sa_sigaction = aio_read_completion_handler ;
99- sa -> sa_flags = SA_SIGINFO | SA_RESTART ;
100- sigaction (SIGRTMIN + 1 , sa , NULL );
101-
102- /* Install Write Handler */
103- sa = malloc (sizeof (struct sigaction ));
104- sigemptyset (& sa -> sa_mask );
105- sa -> sa_sigaction = aio_write_completion_handler ;
106- sa -> sa_flags = SA_SIGINFO | SA_RESTART ;
107- sigaction (SIGRTMIN + 2 , sa , NULL );
76+ return ;
10877}
10978
11079static PyObject *
@@ -115,7 +84,7 @@ pyaio_read(PyObject *dummy, PyObject *args) {
11584
11685 Pyaio_cb * aio ;
11786 PyObject * callback , * return_ ;
118-
87+ Py_XINCREF ( args );
11988 if (PyArg_ParseTuple (args , "innO:set_callback" , & fd , & offset , & numbytes ,
12089 & callback )) {
12190 if (!PyCallable_Check (callback )) {
@@ -125,21 +94,22 @@ pyaio_read(PyObject *dummy, PyObject *args) {
12594 }
12695 Py_XINCREF (callback ); /* Add a reference to new callback */
12796 }
128-
97+ Py_XDECREF ( args );
12998 aio = malloc (sizeof (Pyaio_cb ));
13099
131100 aio -> cb = malloc (sizeof (struct aiocb ));
132101 bzero ((char * ) aio -> cb , sizeof (struct aiocb ));
133102
134103 aio -> callback = callback ;
104+ aio -> buffer = NULL ;
135105
136106 aio -> cb -> aio_buf = malloc ((numbytes ) * sizeof (char ));
137107 aio -> cb -> aio_fildes = fd ;
138108 aio -> cb -> aio_nbytes = numbytes ;
139109 aio -> cb -> aio_offset = offset ;
140- aio -> cb -> aio_sigevent .sigev_notify = SIGEV_SIGNAL ;
141- aio -> cb -> aio_sigevent .sigev_signo = SIGRTMIN + 1 ;
110+ aio -> cb -> aio_sigevent .sigev_notify = SIGEV_THREAD ; /* EvIL */
142111 aio -> cb -> aio_sigevent .sigev_notify_attributes = NULL ;
112+ aio -> cb -> aio_sigevent .sigev_notify_function = aio_completion_handler ;
143113 aio -> cb -> aio_sigevent .sigev_value .sival_ptr = aio ;
144114
145115 ret = aio_read (aio -> cb );
@@ -165,7 +135,7 @@ pyaio_write(PyObject *dummy, PyObject *args) {
165135
166136 Pyaio_cb * aio ;
167137 PyObject * callback , * return_ ;
168-
138+ Py_XINCREF ( args );
169139 if (PyArg_ParseTuple (args , "iOnO:set_callback" , & fd , & buffer ,
170140 & offset , & callback )) {
171141 if (!PyCallable_Check (callback )) {
@@ -180,7 +150,7 @@ pyaio_write(PyObject *dummy, PyObject *args) {
180150 }
181151 Py_XINCREF (callback ); /* Add a reference to new callback */
182152 }
183-
153+ Py_XDECREF ( args );
184154 /* Get a Memoryview */
185155 if (!PyMemoryView_Check (buffer )) {
186156 buffer = PyMemoryView_GetContiguous (buffer , PyBUF_READ , 'C' );
@@ -199,9 +169,9 @@ pyaio_write(PyObject *dummy, PyObject *args) {
199169 aio -> cb -> aio_fildes = fd ;
200170 aio -> cb -> aio_nbytes = buffer_view -> len ;
201171 aio -> cb -> aio_offset = offset ;
202- aio -> cb -> aio_sigevent .sigev_notify = SIGEV_SIGNAL ;
203- aio -> cb -> aio_sigevent .sigev_signo = SIGRTMIN + 2 ;
172+ aio -> cb -> aio_sigevent .sigev_notify = SIGEV_THREAD ;
204173 aio -> cb -> aio_sigevent .sigev_notify_attributes = NULL ;
174+ aio -> cb -> aio_sigevent .sigev_notify_function = aio_completion_handler ;
205175 aio -> cb -> aio_sigevent .sigev_value .sival_ptr = aio ;
206176
207177 ret = aio_write (aio -> cb );
@@ -273,8 +243,6 @@ init_pyaio(void) {
273243 return NULL ;
274244 }
275245
276- init_sig_handlers ();
277-
278246 return m ;
279247}
280248
0 commit comments