af111362b206ed20164fb8191ab829bfd3804638
[kai/samba.git] / source / smbd / process_thread.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    thread model: standard (1 thread per client connection)
5
6    Copyright (C) Andrew Tridgell 2003-2005
7    Copyright (C) James J Myers 2003 <myersjj@samba.org>
8    Copyright (C) Stefan (metze) Metzmacher 2004
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "version.h"
27 #include <pthread.h>
28 #ifdef HAVE_BACKTRACE
29 #include <execinfo.h>
30 #endif
31 #include "system/wait.h"
32 #include "system/filesys.h"
33 #include "lib/events/events.h"
34 #include "dlinklist.h"
35 #include "smb_server/smb_server.h"
36 #include "mutex.h"
37
38 /* For sepecifiying event context to GSSAPI below */
39 #include "heimdal/lib/gssapi/gssapi_locl.h"
40
41 struct new_conn_state {
42         struct event_context *ev;
43         struct socket_context *sock;
44         void (*new_conn)(struct event_context *, struct socket_context *, uint32_t , void *);
45         void *private;
46 };
47
48 static void *thread_connection_fn(void *thread_parm)
49 {
50         struct new_conn_state *new_conn = talloc_get_type(thread_parm, struct new_conn_state);
51
52         new_conn->new_conn(new_conn->ev, new_conn->sock, pthread_self(), new_conn->private);
53
54         /* run this connection from here */
55         event_loop_wait(new_conn->ev);
56
57         talloc_free(new_conn);
58
59         return NULL;
60 }
61
62 /*
63   called when a listening socket becomes readable
64 */
65 static void thread_accept_connection(struct event_context *ev, 
66                                      struct socket_context *sock,
67                                      void (*new_conn)(struct event_context *, struct socket_context *, 
68                                                       uint32_t , void *), 
69                                      void *private)
70 {               
71         NTSTATUS status;
72         int rc;
73         pthread_t thread_id;
74         pthread_attr_t thread_attr;
75         struct new_conn_state *state;
76         struct event_context *ev2;
77
78         ev2 = event_context_init(ev);
79         if (ev2 == NULL) return;
80
81         state = talloc(ev2, struct new_conn_state);
82         if (state == NULL) {
83                 talloc_free(ev2);
84                 return;
85         }
86
87         state->new_conn = new_conn;
88         state->private  = private;
89         state->ev       = ev2;
90
91         /* accept an incoming connection. */
92         status = socket_accept(sock, &state->sock);
93         if (!NT_STATUS_IS_OK(status)) {
94                 talloc_free(ev2);
95                 /* We need to throttle things until the system clears
96                    enough resources to handle this new socket. If we
97                    don't then we will spin filling the log and causing
98                    more problems. We don't panic as this is probably a
99                    temporary resource constraint */
100                 sleep(1);
101                 return;
102         }
103
104         talloc_steal(state, state->sock);
105
106         pthread_attr_init(&thread_attr);
107         pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
108         rc = pthread_create(&thread_id, &thread_attr, thread_connection_fn, state);
109         pthread_attr_destroy(&thread_attr);
110         if (rc == 0) {
111                 DEBUG(4,("accept_connection_thread: created thread_id=%lu for fd=%d\n", 
112                         (unsigned long int)thread_id, socket_get_fd(sock)));
113         } else {
114                 DEBUG(0,("accept_connection_thread: thread create failed for fd=%d, rc=%d\n", socket_get_fd(sock), rc));
115                 talloc_free(ev2);
116         }
117 }
118
119
120 struct new_task_state {
121         struct event_context *ev;
122         void (*new_task)(struct event_context *, uint32_t , void *);
123         void *private;
124 };
125
126 static void *thread_task_fn(void *thread_parm)
127 {
128         struct new_task_state *new_task = talloc_get_type(thread_parm, struct new_task_state);
129
130         new_task->new_task(new_task->ev, pthread_self(), new_task->private);
131
132         /* run this connection from here */
133         event_loop_wait(new_task->ev);
134
135         talloc_free(new_task);
136
137         return NULL;
138 }
139
140 /*
141   called when a new task is needed
142 */
143 static void thread_new_task(struct event_context *ev, 
144                             void (*new_task)(struct event_context *, uint32_t , void *), 
145                             void *private)
146 {               
147         int rc;
148         pthread_t thread_id;
149         pthread_attr_t thread_attr;
150         struct new_task_state *state;
151         struct event_context *ev2;
152
153         ev2 = event_context_init(ev);
154         if (ev2 == NULL) return;
155
156         state = talloc(ev2, struct new_task_state);
157         if (state == NULL) {
158                 talloc_free(ev2);
159                 return;
160         }
161
162         state->new_task = new_task;
163         state->private  = private;
164         state->ev       = ev2;
165
166         pthread_attr_init(&thread_attr);
167         pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
168         rc = pthread_create(&thread_id, &thread_attr, thread_task_fn, state);
169         pthread_attr_destroy(&thread_attr);
170         if (rc == 0) {
171                 DEBUG(4,("thread_new_task: created thread_id=%lu\n", 
172                          (unsigned long int)thread_id));
173         } else {
174                 DEBUG(0,("thread_new_task: thread create failed rc=%d\n", rc));
175                 talloc_free(ev2);
176         }
177 }
178
179 /* called when a task goes down */
180 static void thread_terminate(struct event_context *event_ctx, const char *reason) 
181 {
182         DEBUG(10,("thread_terminate: reason[%s]\n",reason));
183
184         talloc_free(event_ctx);
185
186         /* terminate this thread */
187         pthread_exit(NULL);  /* thread cleanup routine will do actual cleanup */
188 }
189
190 /*
191   mutex init function for thread model
192 */
193 static int thread_mutex_init(smb_mutex_t *mutex, const char *name)
194 {
195         pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
196         mutex->mutex = memdup(&m, sizeof(m));
197         if (! mutex->mutex) {
198                 errno = ENOMEM;
199                 return -1;
200         }
201         return pthread_mutex_init((pthread_mutex_t *)mutex->mutex, NULL);
202 }
203
204 /*
205   mutex destroy function for thread model
206 */
207 static int thread_mutex_destroy(smb_mutex_t *mutex, const char *name)
208 {
209         return pthread_mutex_destroy((pthread_mutex_t *)mutex->mutex);
210 }
211
212 static void mutex_start_timer(struct timeval *tp1)
213 {
214         gettimeofday(tp1,NULL);
215 }
216
217 static double mutex_end_timer(struct timeval tp1)
218 {
219         struct timeval tp2;
220         gettimeofday(&tp2,NULL);
221         return((tp2.tv_sec - tp1.tv_sec) + 
222                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
223 }
224
225 /*
226   mutex lock function for thread model
227 */
228 static int thread_mutex_lock(smb_mutex_t *mutexP, const char *name)
229 {
230         pthread_mutex_t *mutex = (pthread_mutex_t *)mutexP->mutex;
231         int rc;
232         double t;
233         struct timeval tp1;
234         /* Test below is ONLY for debugging */
235         if ((rc = pthread_mutex_trylock(mutex))) {
236                 if (rc == EBUSY) {
237                         mutex_start_timer(&tp1);
238                         printf("mutex lock: thread %d, lock %s not available\n", 
239                                 (uint32_t)pthread_self(), name);
240                         print_suspicious_usage("mutex_lock", name);
241                         pthread_mutex_lock(mutex);
242                         t = mutex_end_timer(tp1);
243                         printf("mutex lock: thread %d, lock %s now available, waited %g seconds\n", 
244                                 (uint32_t)pthread_self(), name, t);
245                         return 0;
246                 }
247                 printf("mutex lock: thread %d, lock %s failed rc=%d\n", 
248                                 (uint32_t)pthread_self(), name, rc);
249                 SMB_ASSERT(errno == 0); /* force error */
250         }
251         return 0;
252 }
253
254 /* 
255    mutex unlock for thread model
256 */
257 static int thread_mutex_unlock(smb_mutex_t *mutex, const char *name)
258 {
259         return pthread_mutex_unlock((pthread_mutex_t *)mutex->mutex);
260 }
261
262 /*****************************************************************
263  Read/write lock routines.
264 *****************************************************************/  
265 /*
266   rwlock init function for thread model
267 */
268 static int thread_rwlock_init(smb_rwlock_t *rwlock, const char *name)
269 {
270         pthread_rwlock_t m = PTHREAD_RWLOCK_INITIALIZER;
271         rwlock->rwlock = memdup(&m, sizeof(m));
272         if (! rwlock->rwlock) {
273                 errno = ENOMEM;
274                 return -1;
275         }
276         return pthread_rwlock_init((pthread_rwlock_t *)rwlock->rwlock, NULL);
277 }
278
279 /*
280   rwlock destroy function for thread model
281 */
282 static int thread_rwlock_destroy(smb_rwlock_t *rwlock, const char *name)
283 {
284         return pthread_rwlock_destroy((pthread_rwlock_t *)rwlock->rwlock);
285 }
286
287 /*
288   rwlock lock for read function for thread model
289 */
290 static int thread_rwlock_lock_read(smb_rwlock_t *rwlockP, const char *name)
291 {
292         pthread_rwlock_t *rwlock = (pthread_rwlock_t *)rwlockP->rwlock;
293         int rc;
294         double t;
295         struct timeval tp1;
296         /* Test below is ONLY for debugging */
297         if ((rc = pthread_rwlock_tryrdlock(rwlock))) {
298                 if (rc == EBUSY) {
299                         mutex_start_timer(&tp1);
300                         printf("rwlock lock_read: thread %d, lock %s not available\n", 
301                                 (uint32_t)pthread_self(), name);
302                         print_suspicious_usage("rwlock_lock_read", name);
303                         pthread_rwlock_rdlock(rwlock);
304                         t = mutex_end_timer(tp1);
305                         printf("rwlock lock_read: thread %d, lock %s now available, waited %g seconds\n", 
306                                 (uint32_t)pthread_self(), name, t);
307                         return 0;
308                 }
309                 printf("rwlock lock_read: thread %d, lock %s failed rc=%d\n", 
310                                 (uint32_t)pthread_self(), name, rc);
311                 SMB_ASSERT(errno == 0); /* force error */
312         }
313         return 0;
314 }
315
316 /*
317   rwlock lock for write function for thread model
318 */
319 static int thread_rwlock_lock_write(smb_rwlock_t *rwlockP, const char *name)
320 {
321         pthread_rwlock_t *rwlock = (pthread_rwlock_t *)rwlockP->rwlock;
322         int rc;
323         double t;
324         struct timeval tp1;
325         /* Test below is ONLY for debugging */
326         if ((rc = pthread_rwlock_trywrlock(rwlock))) {
327                 if (rc == EBUSY) {
328                         mutex_start_timer(&tp1);
329                         printf("rwlock lock_write: thread %d, lock %s not available\n", 
330                                 (uint32_t)pthread_self(), name);
331                         print_suspicious_usage("rwlock_lock_write", name);
332                         pthread_rwlock_wrlock(rwlock);
333                         t = mutex_end_timer(tp1);
334                         printf("rwlock lock_write: thread %d, lock %s now available, waited %g seconds\n", 
335                                 (uint32_t)pthread_self(), name, t);
336                         return 0;
337                 }
338                 printf("rwlock lock_write: thread %d, lock %s failed rc=%d\n", 
339                                 (uint32_t)pthread_self(), name, rc);
340                 SMB_ASSERT(errno == 0); /* force error */
341         }
342         return 0;
343 }
344
345
346 /* 
347    rwlock unlock for thread model
348 */
349 static int thread_rwlock_unlock(smb_rwlock_t *rwlock, const char *name)
350 {
351         return pthread_rwlock_unlock((pthread_rwlock_t *)rwlock->rwlock);
352 }
353
354 /*****************************************************************
355  Log suspicious usage (primarily for possible thread-unsafe behavior.
356 *****************************************************************/  
357 static void thread_log_suspicious_usage(const char* from, const char* info)
358 {
359         DEBUG(1,("log_suspicious_usage: from %s info='%s'\n", from, info));
360 #ifdef HAVE_BACKTRACE
361         {
362                 void *addresses[10];
363                 int num_addresses = backtrace(addresses, 8);
364                 char **bt_symbols = backtrace_symbols(addresses, num_addresses);
365                 int i;
366
367                 if (bt_symbols) {
368                         for (i=0; i<num_addresses; i++) {
369                                 DEBUG(1,("log_suspicious_usage: %s%s\n", DEBUGTAB(1), bt_symbols[i]));
370                         }
371                         free(bt_symbols);
372                 }
373         }
374 #endif
375 }
376
377 /*****************************************************************
378  Log suspicious usage to stdout (primarily for possible thread-unsafe behavior.
379  Used in mutex code where DEBUG calls would cause recursion.
380 *****************************************************************/  
381 static void thread_print_suspicious_usage(const char* from, const char* info)
382 {
383         printf("log_suspicious_usage: from %s info='%s'\n", from, info);
384 #ifdef HAVE_BACKTRACE
385         {
386                 void *addresses[10];
387                 int num_addresses = backtrace(addresses, 8);
388                 char **bt_symbols = backtrace_symbols(addresses, num_addresses);
389                 int i;
390
391                 if (bt_symbols) {
392                         for (i=0; i<num_addresses; i++) {
393                                 printf("log_suspicious_usage: %s%s\n", DEBUGTAB(1), bt_symbols[i]);
394                         }
395                         free(bt_symbols);
396                 }
397         }
398 #endif
399 }
400
401 static uint32_t thread_get_task_id(void)
402 {
403         return (uint32_t)pthread_self();
404 }
405
406 static void thread_log_task_id(int fd)
407 {
408         char *s= NULL;
409         
410         asprintf(&s, "thread %u: ", (uint32_t)pthread_self());
411         if (!s) return;
412         write(fd, s, strlen(s));
413         free(s);
414 }
415
416 /****************************************************************************
417 catch serious errors
418 ****************************************************************************/
419 static void thread_sig_fault(int sig)
420 {
421         DEBUG(0,("===============================================================\n"));
422         DEBUG(0,("TERMINAL ERROR: Recursive signal %d in thread %lu (%s)\n",sig,(unsigned long int)pthread_self(),SAMBA_VERSION_STRING));
423         DEBUG(0,("===============================================================\n"));
424         exit(1); /* kill the whole server for now */
425 }
426
427 /*******************************************************************
428 setup our recursive fault handlers
429 ********************************************************************/
430 static void thread_fault_setup(void)
431 {
432 #ifdef SIGSEGV
433         CatchSignal(SIGSEGV,SIGNAL_CAST thread_sig_fault);
434 #endif
435 #ifdef SIGBUS
436         CatchSignal(SIGBUS,SIGNAL_CAST thread_sig_fault);
437 #endif
438 #ifdef SIGABRT
439         CatchSignal(SIGABRT,SIGNAL_CAST thread_sig_fault);
440 #endif
441 }
442
443 /*******************************************************************
444 report a fault in a thread
445 ********************************************************************/
446 static void thread_fault_handler(int sig)
447 {
448         static int counter;
449         
450         /* try to catch recursive faults */
451         thread_fault_setup();
452         
453         counter++;      /* count number of faults that have occurred */
454
455         DEBUG(0,("===============================================================\n"));
456         DEBUG(0,("INTERNAL ERROR: Signal %d in thread %lu (%s)\n",sig,(unsigned long int)pthread_self(),SAMBA_VERSION_STRING));
457         DEBUG(0,("Please read the file BUGS.txt in the distribution\n"));
458         DEBUG(0,("===============================================================\n"));
459 #ifdef HAVE_BACKTRACE
460         {
461                 void *addresses[10];
462                 int num_addresses = backtrace(addresses, 8);
463                 char **bt_symbols = backtrace_symbols(addresses, num_addresses);
464                 int i;
465
466                 if (bt_symbols) {
467                         for (i=0; i<num_addresses; i++) {
468                                 DEBUG(1,("fault_report: %s%s\n", DEBUGTAB(1), bt_symbols[i]));
469                         }
470                         free(bt_symbols);
471                 }
472         }
473 #endif
474         pthread_exit(NULL); /* terminate failing thread only */
475 }
476
477 /*
478   called when the process model is selected
479 */
480 static void thread_model_init(struct event_context *event_context)
481 {
482         struct mutex_ops m_ops;
483         struct debug_ops d_ops;
484
485         ZERO_STRUCT(m_ops);
486         ZERO_STRUCT(d_ops);
487
488         /* register mutex/rwlock handlers */
489         m_ops.mutex_init = thread_mutex_init;
490         m_ops.mutex_lock = thread_mutex_lock;
491         m_ops.mutex_unlock = thread_mutex_unlock;
492         m_ops.mutex_destroy = thread_mutex_destroy;
493         
494         m_ops.rwlock_init = thread_rwlock_init;
495         m_ops.rwlock_lock_write = thread_rwlock_lock_write;
496         m_ops.rwlock_lock_read = thread_rwlock_lock_read;
497         m_ops.rwlock_unlock = thread_rwlock_unlock;
498         m_ops.rwlock_destroy = thread_rwlock_destroy;
499
500         register_mutex_handlers("thread", &m_ops);
501
502         register_fault_handler("thread", thread_fault_handler);
503
504         d_ops.log_suspicious_usage = thread_log_suspicious_usage;
505         d_ops.print_suspicious_usage = thread_print_suspicious_usage;
506         d_ops.get_task_id = thread_get_task_id;
507         d_ops.log_task_id = thread_log_task_id;
508
509         register_debug_handlers("thread", &d_ops);
510
511         /* Hack to ensure that GSSAPI uses the right event context */
512         gssapi_krb5_init_ev(event_context);
513 }
514
515
516 static const struct model_ops thread_ops = {
517         .name                   = "thread",
518         .model_init             = thread_model_init,
519         .accept_connection      = thread_accept_connection,
520         .new_task               = thread_new_task,
521         .terminate              = thread_terminate,
522 };
523
524 /*
525   initialise the thread process model, registering ourselves with the model subsystem
526  */
527 NTSTATUS process_model_thread_init(void)
528 {
529         NTSTATUS ret;
530
531         /* register ourselves with the PROCESS_MODEL subsystem. */
532         ret = register_process_model(&thread_ops);
533         if (!NT_STATUS_IS_OK(ret)) {
534                 DEBUG(0,("Failed to register process_model 'thread'!\n"));
535                 return ret;
536         }
537
538         return ret;
539 }