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