]> git.sur5r.net Git - openldap/blob - servers/slapd/connection.c
Use pthread_detach() to detach connection threads instead of
[openldap] / servers / slapd / connection.c
1 #include "portable.h"
2
3 #include <stdio.h>
4
5 #include <ac/errno.h>
6 #include <ac/signal.h>
7 #include <ac/socket.h>
8 #include <ac/string.h>
9 #include <ac/time.h>
10
11 #include "slap.h"
12
13 struct co_arg {
14         Connection      *co_conn;
15         Operation       *co_op;
16 };
17
18 /*
19  * connection_activity - handle the request operation op on connection
20  * conn.  This routine figures out what kind of operation it is and
21  * calls the appropriate stub to handle it.
22  */
23
24 static void *
25 connection_operation( void *arg_v )
26 {
27         struct co_arg   *arg = arg_v;
28         unsigned long   len;
29
30         pthread_mutex_lock( &arg->co_conn->c_opsmutex );
31         arg->co_conn->c_opsinitiated++;
32         pthread_mutex_unlock( &arg->co_conn->c_opsmutex );
33
34         pthread_mutex_lock( &ops_mutex );
35         ops_initiated++;
36         pthread_mutex_unlock( &ops_mutex );
37
38         switch ( arg->co_op->o_tag ) {
39         case LDAP_REQ_BIND:
40                 do_bind( arg->co_conn, arg->co_op );
41                 break;
42
43 #ifdef LDAP_COMPAT30
44         case LDAP_REQ_UNBIND_30:
45 #endif
46         case LDAP_REQ_UNBIND:
47                 do_unbind( arg->co_conn, arg->co_op );
48                 break;
49
50         case LDAP_REQ_ADD:
51                 do_add( arg->co_conn, arg->co_op );
52                 break;
53
54 #ifdef LDAP_COMPAT30
55         case LDAP_REQ_DELETE_30:
56 #endif
57         case LDAP_REQ_DELETE:
58                 do_delete( arg->co_conn, arg->co_op );
59                 break;
60
61         case LDAP_REQ_MODRDN:
62                 do_modrdn( arg->co_conn, arg->co_op );
63                 break;
64
65         case LDAP_REQ_MODIFY:
66                 do_modify( arg->co_conn, arg->co_op );
67                 break;
68
69         case LDAP_REQ_COMPARE:
70                 do_compare( arg->co_conn, arg->co_op );
71                 break;
72
73         case LDAP_REQ_SEARCH:
74                 do_search( arg->co_conn, arg->co_op );
75                 break;
76
77 #ifdef LDAP_COMPAT30
78         case LDAP_REQ_ABANDON_30:
79 #endif
80         case LDAP_REQ_ABANDON:
81                 do_abandon( arg->co_conn, arg->co_op );
82                 break;
83
84         default:
85                 Debug( LDAP_DEBUG_ANY, "unknown request 0x%lx\n",
86                     arg->co_op->o_tag, 0, 0 );
87                 break;
88         }
89
90         pthread_mutex_lock( &arg->co_conn->c_opsmutex );
91         arg->co_conn->c_opscompleted++;
92         slap_op_delete( &arg->co_conn->c_ops, arg->co_op );
93         pthread_mutex_unlock( &arg->co_conn->c_opsmutex );
94
95         free( (char *) arg );
96
97         pthread_mutex_lock( &ops_mutex );
98         ops_completed++;
99         pthread_mutex_unlock( &ops_mutex );
100
101         pthread_mutex_lock( &active_threads_mutex );
102         active_threads--;
103         if( active_threads < 1 ) {
104                 pthread_cond_signal(&active_threads_cond);
105         }
106         pthread_mutex_unlock( &active_threads_mutex );
107         return NULL;
108 }
109
110 void
111 connection_activity(
112     Connection *conn
113 )
114 {
115 #ifndef HAVE_PTHREAD_DETACH
116         pthread_attr_t  attr;
117 #endif
118         struct co_arg   *arg;
119         unsigned long   tag, len;
120         long            msgid;
121         BerElement      *ber;
122         char            *tmpdn;
123
124         if ( conn->c_currentber == NULL && (conn->c_currentber = ber_alloc())
125             == NULL ) {
126                 Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
127                 return;
128         }
129
130         errno = 0;
131         if ( (tag = ber_get_next( &conn->c_sb, &len, conn->c_currentber ))
132             != LDAP_TAG_MESSAGE ) {
133                 Debug( LDAP_DEBUG_TRACE,
134                     "ber_get_next on fd %d failed errno %d (%s)\n",
135                     conn->c_sb.sb_sd, errno, errno > -1 && errno < sys_nerr ?
136                     sys_errlist[errno] : "unknown" );
137                 Debug( LDAP_DEBUG_TRACE, "*** got %ld of %lu so far\n",
138                     (long)(conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf),
139                     conn->c_currentber->ber_len, 0 );
140
141                 if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
142                         /* log, close and send error */
143                         ber_free( conn->c_currentber, 1 );
144                         conn->c_currentber = NULL;
145
146                         close_connection( conn, conn->c_connid, -1 );
147                 }
148
149                 return;
150         }
151         ber = conn->c_currentber;
152         conn->c_currentber = NULL;
153
154         if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID ) {
155                 /* log, close and send error */
156                 Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", tag, 0,
157                     0 );
158                 ber_free( ber, 1 );
159
160                 close_connection( conn, conn->c_connid, -1 );
161                 return;
162         }
163
164         if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
165                 /* log, close and send error */
166                 Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n", tag, 0,
167                     0 );
168                 ber_free( ber, 1 );
169
170                 close_connection( conn, conn->c_connid, -1 );
171                 return;
172         }
173
174 #ifdef LDAP_COMPAT30
175         if ( conn->c_version == 30 ) {
176                 (void) ber_skip_tag( ber, &len );
177         }
178 #endif
179
180         arg = (struct co_arg *) ch_malloc( sizeof(struct co_arg) );
181         arg->co_conn = conn;
182
183         pthread_mutex_lock( &conn->c_dnmutex );
184         if ( conn->c_dn != NULL ) {
185                 tmpdn = ch_strdup( conn->c_dn );
186         } else {
187                 tmpdn = NULL;
188         }
189         pthread_mutex_unlock( &conn->c_dnmutex );
190
191         pthread_mutex_lock( &conn->c_opsmutex );
192         arg->co_op = slap_op_add( &conn->c_ops, ber, msgid, tag, tmpdn,
193             conn->c_opsinitiated, conn->c_connid );
194         pthread_mutex_unlock( &conn->c_opsmutex );
195
196         if ( tmpdn != NULL ) {
197                 free( tmpdn );
198         }
199
200 #ifdef HAVE_PTHREAD_DETACH
201         if ( pthread_create( &arg->co_op->o_tid, NULL,
202             connection_operation, (void *) arg ) != 0 ) {
203                 Debug( LDAP_DEBUG_ANY, "pthread_create failed\n", 0, 0, 0 );
204         } else {
205                 pthread_mutex_lock( &active_threads_mutex );
206                 active_threads++;
207                 pthread_mutex_unlock( &active_threads_mutex );
208         }
209
210 #if !defined(HAVE_PTHREADS_D4)
211         pthread_detach( arg->co_op->o_tid );
212 #else
213         pthread_detach( &arg->co_op->o_tid );
214 #endif
215
216 #else /* !pthread detach */
217
218         pthread_attr_init( &attr );
219         pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
220 #if !defined(HAVE_PTHREADS_D4)
221         /* POSIX_THREADS or compatible
222          * This is a draft 10 or standard pthreads implementation
223          */
224         if ( pthread_create( &arg->co_op->o_tid, &attr,
225             connection_operation, (void *) arg ) != 0 ) {
226                 Debug( LDAP_DEBUG_ANY, "pthread_create failed\n", 0, 0, 0 );
227         } else {
228                 pthread_mutex_lock( &active_threads_mutex );
229                 active_threads++;
230                 pthread_mutex_unlock( &active_threads_mutex );
231         }
232 #else   /* pthread draft4  */
233         /*
234          * This is a draft 4 or earlier pthreads implementation
235          */
236         if ( pthread_create( &arg->co_op->o_tid, attr,
237             connection_operation, (void *) arg ) != 0 ) {
238                 Debug( LDAP_DEBUG_ANY, "pthread_create failed\n", 0, 0, 0 );
239         } else {
240                 pthread_mutex_lock( &active_threads_mutex );
241                 active_threads++;
242                 pthread_mutex_unlock( &active_threads_mutex );
243         }
244 #endif  /* pthread draft4 */
245         pthread_attr_destroy( &attr );
246 #endif
247 }