modules/sk/sk_socket.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- SK_atoport
- SK_close
- SK_getsock
- SK_accept_connection
- SK_read
- SK_write
- SK_gets
- SK_puts
- SK_putc
- SK_getc
- SK_getpeername
- SK_getpeerip
- SK_cd_puts
- SK_cd_gets
- SK_cd_close
- SK_cd_printf
- SK_init
- func_sigusr
- sk_watchdog
- SK_watchstart
- SK_watchstop
- SK_watchkill
- SK_watchexec
- SK_watchclear
1 /***************************************
2 $Revision: 1.6 $
3
4 Example code: A socket module.
5
6 Status: NOT REVUED, NOT TESTED
7
8 +html+ <DL COMPACT>
9 +html+ <DT>Online References:
10 +html+ <DD><UL>
11 +html+ <LI>Adapted from <A HREF="http://www.ibrado.com/sock-faq/sfaq.html#faq65">sample source code</A>.
12 +html+ </UL>
13 +html+ </DL>
14 +html+ <PRE>
15 +html+ </PRE>
16
17 ******************/ /******************
18 Modification History:
19 ottrey (08/03/1999) Created from sockhelp.c.
20 ottrey (08/03/1998) Heavily butchered.
21 joao (22/06/1999) Modified socket creation and accepts.
22 ******************/ /******************
23 REMINDER: PUT THE PROPER COPYRIGHT NOTICE HERE
24 ***************************************/
25 #include <arpa/inet.h>
26 #include "socket.h"
27 #include "constants.h"
28 #include "stubs.h"
29
30 #include "iproutines.h"
31 #include "memwrap.h"
32
33 #include <pthread.h>
34
35 extern int h_errno;
36
37
38 /*+ String sizes +*/
39 #define STR_S 63
40 #define STR_M 255
41 #define STR_L 1023
42 #define STR_XL 4095
43 #define STR_XXL 16383
44
45 /* SK_atoport() */
46 /*++++++++++++++++++++++++++++++++++++++
47 Take a service name, and a service type, and return a port number. If the
48 service name is not found, it tries it as a decimal number. The number
49 returned is byte ordered for the network.
50
51 char *service Service name (or port number).
52
53 char *proto Protocol (eg "tcp").
54
55 More:
56 +html+ <PRE>
57 Authors:
58 ottrey
59
60 +html+ </PRE><DL COMPACT>
61 +html+ <DT>Online References:
62 +html+ <DD><UL>
63 +html+ </UL></DL>
64
65 ++++++++++++++++++++++++++++++++++++++*/
66 int SK_atoport(const char *service, const char *proto) {
/* [<][>][^][v][top][bottom][index][help] */
67 int port;
68 long int lport;
69 struct servent *serv;
70 char *errpos;
71 struct servent result;
72 char buffer[STR_XXL];
73
74 /* First try to read it from /etc/services */
75
76 /* serv = getservbyname(service, proto); */
77 serv = getservbyname_r(service, proto, &result, buffer, sizeof(buffer));
78 if (serv != NULL)
79 port = serv->s_port;
80 else { /* Not in services, maybe a number? */
81 lport = strtol(service,&errpos,0);
82 if ( (errpos[0] != 0) || (lport < 1) || (lport > 65535) )
83 return -1; /* Invalid port address */
84 port = htons(lport);
85 }
86 return port;
87 } /* SK_atoport() */
88
89
90 /* SK_close() */
91 /*++++++++++++++++++++++++++++++++++++++
92
93 More:
94 +html+ <PRE>
95 Authors:
96 ottrey
97
98 +html+ </PRE><DL COMPACT>
99 +html+ <DT>Online References:
100 +html+ <DD><UL>
101 +html+ </UL></DL>
102
103 ++++++++++++++++++++++++++++++++++++++*/
104 int SK_close(int socket) {
/* [<][>][^][v][top][bottom][index][help] */
105 ER_dbg_va(FAC_SK, ASP_SK_GEN, "Closing socket... %d", socket);
106
107 return close(socket);
108 }
109
110 /* SK_getsock() */
111 /*++++++++++++++++++++++++++++++++++++++
112
113 This function creates a socket and binds to it
114
115 int SK_getsock The new socket
116
117 int socket_type SOCK_STREAM or SOCK_DGRAM (TCP or UDP sockets)
118
119 u_short port The port to listen on. Remember that ports < 1024 are
120 reserved for the root user. Must be passed in network byte
121 order (see "man htons").
122
123 uint32_t bind_address Address to bind to, in network order.
124 More:
125 +html+ <PRE>
126 Authors:
127 ottrey
128 joao
129
130 +html+ </PRE><DL COMPACT>
131 +html+ <DT>Online References:
132 +html+ <DD><UL>
133 +html+ </UL></DL>
134
135 ++++++++++++++++++++++++++++++++++++++*/
136 int SK_getsock(int socket_type, u_short port, uint32_t bind_address) {
/* [<][>][^][v][top][bottom][index][help] */
137 struct sockaddr_in address;
138 int listening_socket;
139 int reuse_addr = 1;
140
141 /* Setup internet address information.
142 This is used with the bind() call */
143 memset((char *) &address, 0, sizeof(address));
144 address.sin_family = AF_INET;
145 address.sin_port = port;
146 address.sin_addr.s_addr = bind_address;
147
148 /* Map all of the signals and exit routine */
149
150 listening_socket = socket(AF_INET, socket_type, 0);
151 if (listening_socket < 0) {
152 perror("socket");
153 exit(EXIT_FAILURE);
154 }
155
156 setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse_addr, sizeof(reuse_addr));
157
158 if (bind(listening_socket, (struct sockaddr *) &address, sizeof(address)) < 0) {
159 perror("bind");
160 close(listening_socket);
161 exit(EXIT_FAILURE);
162 }
163
164
165 if (socket_type == SOCK_STREAM) {
166 listen(listening_socket, 5); /* Queue up to five connections before
167 having them automatically rejected. */
168 }
169
170 return listening_socket;
171 } /* SK_getsock() */
172
173 /*++++++++++++++++++++++++++++++++++++++
174
175 Wait for an incoming connection on the specified socket
176
177 int SK_accept_connection The socket for communicating to the client
178
179 int listening_socket The socket that the server is bound to
180
181 More:
182 +html+ <PRE>
183 Authors:
184 joao
185 +html+ </PRE>
186 ++++++++++++++++++++++++++++++++++++++*/
187 int SK_accept_connection(int listening_socket) {
/* [<][>][^][v][top][bottom][index][help] */
188 int connected_socket = -1;
189
190 while(connected_socket < 0) {
191
192 ER_dbg_va(FAC_SK, ASP_SK_GEN,
193 "Going to accept connections on socket : %d",listening_socket);
194
195 /* XXX joao - ? - why is this here?
196 fflush(NULL);
197 */
198
199 connected_socket = accept(listening_socket, NULL, NULL);
200 if (connected_socket < 0) {
201 /* Either a real error occured, or blocking was interrupted for
202 some reason. Only abort execution if a real error occured. */
203 if (errno != EINTR) {
204 perror("accept");
205 close(listening_socket);
206 return(-1);
207 /* no exit, just return with error */
208 } else {
209 continue; /* don't return - do the accept again */
210 }
211 }
212 }
213
214 ER_dbg_va(FAC_SK, ASP_SK_GEN, "client connected on socket %d",
215 connected_socket
216 );
217
218 return connected_socket;
219 }
220
221 /* SK_read() */
222 /*++++++++++++++++++++++++++++++++++++++
223
224 This is just like the read() system call, except that it will make
225 sure that all your data goes through the socket.
226
227 int SK_read The number of bytes read.
228
229 int sockfd The socket file descriptor.
230
231 char *buf The buffer to be read from the socket.
232
233 size_t count The number of bytes in the buffer.
234
235 More:
236 +html+ <PRE>
237 Authors:
238 ottrey
239 +html+ </PRE>
240 ++++++++++++++++++++++++++++++++++++++*/
241 int SK_read(int sockfd, char *buf, size_t count) {
/* [<][>][^][v][top][bottom][index][help] */
242 size_t bytes_read = 0;
243 int this_read;
244
245 while (bytes_read < count) {
246 do
247 this_read = read(sockfd, buf, count - bytes_read);
248 while ( (this_read < 0) && (errno == EINTR) );
249 if (this_read < 0)
250 return this_read;
251 else if (this_read == 0)
252 return bytes_read;
253 bytes_read += this_read;
254 buf += this_read;
255 }
256
257 return count;
258
259 } /* SK_read() */
260
261
262 /* SK_write() */
263 /*++++++++++++++++++++++++++++++++++++++
264
265 This is just like the write() system call, accept that it will
266 make sure that all data is transmitted.
267
268 int sockfd The socket file descriptor.
269
270 char *buf The buffer to be written to the socket.
271
272 size_t count The number of bytes in the buffer.
273
274 More:
275 +html+ <PRE>
276 Authors:
277 ottrey
278
279 +html+ </PRE><DL COMPACT>
280 +html+ <DT>Online References:
281 +html+ <DD><UL>
282 +html+ </UL></DL>
283
284 ++++++++++++++++++++++++++++++++++++++*/
285 int SK_write(int sockfd, const char *buf, size_t count) {
/* [<][>][^][v][top][bottom][index][help] */
286 size_t bytes_sent = 0;
287 int this_write;
288
289
290 ER_dbg_va(FAC_SK, ASP_SK_WRIT,
291 "SK_write = { sockfd=[%d], buf=[%s], count=[%d]",
292 sockfd, buf, count);
293
294 while (bytes_sent < count) {
295 do
296 this_write = write(sockfd, buf, count - bytes_sent);
297 while ( (this_write < 0) && (errno == EINTR) );
298 if (this_write <= 0)
299 return this_write;
300 bytes_sent += this_write;
301 buf += this_write;
302 }
303 return count;
304 } /* SK_write() */
305
306
307 /* SK_gets() */
308 /*++++++++++++++++++++++++++++++++++++++
309
310 This function reads from a socket, until it recieves a linefeed
311 character. It fills the buffer "str" up to the maximum size "count".
312
313 int SK_gets The total_count of bytes read.
314
315 int sockfd The socket file descriptor.
316
317 char *str The buffer to be written from the socket.
318
319 size_t count The number of bytes in the buffer.
320
321 More:
322 +html+ <PRE>
323 Authors:
324 ottrey
325
326 Side Effects:
327 This function will return -1 if the socket is closed during the read operation.
328
329 Note that if a single line exceeds the length of count, the extra data
330 will be read and discarded! You have been warned.
331
332 To Do:
333 Capture the control-c properly!
334
335 +html+ </PRE>
336
337 ++++++++++++++++++++++++++++++++++++++*/
338 int SK_gets(int sockfd, char *str, size_t count) {
/* [<][>][^][v][top][bottom][index][help] */
339 int bytes_read;
340 int total_count = 0;
341 char *current_position;
342 char last_read = 0;
343
344 int control_c = 0;
345
346 current_position = str;
347 while (last_read != 10) {
348
349
350
351 bytes_read = read(sockfd, &last_read, 1);
352 if (bytes_read <= 0) {
353 /* The other side may have closed unexpectedly */
354 return SK_DISCONNECT;
355 /* Is this effective on other platforms than linux? */
356 }
357 if ( (total_count < count) && (last_read != 10) && (last_read !=13) ) {
358 *current_position = last_read;
359 current_position++;
360 total_count++;
361 }
362
363 if (last_read == -1) {
364 bytes_read = read(sockfd, &last_read, 1);
365 if (last_read == -12) {
366 ER_dbg_va(FAC_SK, ASP_SK_GEN,"Client pressed Control-c");
367 control_c = 1;
368 ER_dbg_va(FAC_SK, ASP_SK_GEN,"returning SK_INTERRUPT");
369 return SK_INTERRUPT;
370 }
371 }
372 }
373 if (count > 0) {
374 *current_position = 0;
375 }
376
377 return total_count;
378
379 } /* SK_gets() */
380
381
382 /* SK_puts() */
383 /*++++++++++++++++++++++++++++++++++++++
384
385 This function writes a character string out to a socket.
386
387 int SK_puts The total_count of bytes written,
388 or errors (represented as negative numbers)
389
390 int sockfd The socket file descriptor.
391
392 char *str The buffer to be written from the socket.
393
394 More:
395 +html+ <PRE>
396 Authors:
397 ottrey
398
399 Side Effects:
400 This function will return -1 if the socket is closed during the write operation.
401
402 Note that if a single line exceeds the length of count, the extra data
403 will be read and discarded! You have been warned.
404
405 +html+ </PRE>
406
407 ++++++++++++++++++++++++++++++++++++++*/
408 int SK_puts(int sockfd, const char *str) {
/* [<][>][^][v][top][bottom][index][help] */
409
410 return SK_write(sockfd, str, strlen(str));
411
412 } /* SK_puts() */
413
414 /* SK_putc() */
415 /*++++++++++++++++++++++++++++++++++++++
416
417 int SK_putc This function writes a single character out to a socket.
418
419 int sockfd socket
420 char ch character
421
422 return number of chars written
423
424 ++++++++++++++++++++++++++++++++++++++*/
425 int SK_putc(int sockfd, char ch) {
/* [<][>][^][v][top][bottom][index][help] */
426 return SK_write(sockfd, &ch, 1);
427 }/* SK_putc() */
428
429 /*++++++++++++++++++++++++++++++++++++++
430
431 This function reads a single character from a socket.
432
433 returns EOF when no character can be read.
434
435 ++++++++++++++++++++++++++++++++++++++*/
436 int SK_getc(int sockfd) {
/* [<][>][^][v][top][bottom][index][help] */
437 char ch;
438
439 if( read(sockfd, &ch, 1) <= 0 ) {
440 return EOF;
441 }
442 else {
443 return ch;
444 }
445 }/* SK_getc() */
446
447 /* SK_getpeername() */
448 /*++++++++++++++++++++++++++++++++++++++
449
450 This function will tell you who is at the other end of a connected stream socket.
451 XXX It's not working.
452 XXX ? MB it is...
453
454 int sockfd The socket file descriptor.
455
456 More:
457 +html+ <PRE>
458 Authors:
459 ottrey
460 +html+ </PRE>
461
462 ++++++++++++++++++++++++++++++++++++++*/
463 char *SK_getpeername(int sockfd)
/* [<][>][^][v][top][bottom][index][help] */
464 {
465 char *hostaddress=NULL;
466 struct sockaddr_in addr_in;
467 int namelen=sizeof(addr_in);
468
469 if (getpeername(sockfd, (struct sockaddr *)&addr_in, &namelen) != -1) {
470
471 dieif( wr_malloc((void **)&hostaddress, 16) != UT_OK);
472
473 strcpy(hostaddress, inet_ntoa(addr_in.sin_addr)); /* XXX MT-UNSAFE */
474 }
475
476 return hostaddress;
477
478 } /* SK_getpeername() */
479
480 /* SK_getpeerip */
481 int SK_getpeerip(int sockfd, ip_addr_t *ip) {
/* [<][>][^][v][top][bottom][index][help] */
482 struct sockaddr_in addr_in;
483 int namelen=sizeof(addr_in);
484 int ret=-1;
485
486 memset(& addr_in, 0, sizeof(struct sockaddr_in));
487
488 if (getpeername(sockfd, (struct sockaddr *)(& addr_in), &namelen) != -1) {
489 ret=0;
490 IP_addr_s2b(ip, &addr_in, namelen);
491 }
492
493 return ret;
494 }
495
496 /*-------------------------------------------------------------------
497 * CD varieties of the functions: broken connections get registered
498 * in the connection structure within the query environment
499 * as side effects.
500 * -----------------------------------------------------------------*/
501
502 /* SK_cd_puts() */
503 /*++++++++++++++++++++++++++++++++++++++
504
505 This function writes a character string out to a socket.
506
507 int SK_qe_puts The total_count of bytes written,
508 or errors (represented as negative numbers)
509
510 sk_conn_st *condat connection data
511
512 char *str The buffer to be written from the socket.
513
514 More:
515 if the connection structure has bad status for this connection
516 from previous calls, no write will be attempted.
517
518 +html+ <PRE>
519 Authors:
520 marek
521
522 Side Effects:
523 broken connections get registered
524 in the connection structure within the query environment
525
526 +html+ </PRE>
527
528 ++++++++++++++++++++++++++++++++++++++*/
529 int SK_cd_puts(sk_conn_st *condat, const char *str) {
/* [<][>][^][v][top][bottom][index][help] */
530 int res=SK_puts(condat->sock, str);
531
532 if( res < 0 ){
533 /* set the corresponding rtc flag */
534 condat->rtc |= (-res);
535
536 switch( - res ) {
537 /* dont know what to do and how to log */
538 case SK_DISCONNECT:
539 case SK_INTERRUPT:
540 /*("Thread received a control-c\n");*/
541 case SK_TIMEOUT:
542 /*("Reading timed out\n");*/
543 break;
544 default:
545 /* unexpected error code. bail out */
546 die;
547 }
548 }
549 return res;
550 } /* SK_cd_puts() */
551
552 /* SK_cd_gets() */
553 /*++++++++++++++++++++++++++++++++++++++
554
555 Wrapper around SK_gets.
556
557 int SK_cd_gets The total_count of bytes read,
558 or errors (represented as negative numbers)
559
560 sk_conn_st *condat connection data
561
562 char *str The buffer to be written from the socket.
563
564 More:
565 if the connection structure has bad status for this connection
566 from previous calls, no write will be attempted.
567
568 +html+ <PRE>
569 Authors:
570 marek
571
572 Side Effects:
573 broken connections get registered
574 in the connection structure within the query environment
575
576 +html+ </PRE>
577
578 ++++++++++++++++++++++++++++++++++++++*/
579 int SK_cd_gets(sk_conn_st *condat, char *str, size_t count) {
/* [<][>][^][v][top][bottom][index][help] */
580 fd_set rset;
581 struct timeval *ptm = & condat->rd_timeout;
582 int readcount = 0;
583
584 memset( str, 0, count);
585 FD_ZERO( &rset );
586 FD_SET( condat->sock, &rset );
587
588 if( ptm->tv_sec == 0 && ptm->tv_usec == 0) { /* if timeout undefined,
589 do blocking I/O */
590 ptm = NULL;
591 }
592
593 do {
594 char buf[2];
595 int sel = select( (condat->sock)+1, &rset, NULL, NULL, ptm);
596
597 dieif(sel < 0); /* we don't expect problems */
598
599 if( sel == 0 ) {
600 condat->rtc |= SK_TIMEOUT;
601 break;
602 }
603
604 else {
605 read( condat->sock, buf, 1 );
606 str[readcount] = buf[0];
607 readcount++;
608 if( buf[0] == '\n' ) {
609 break;
610 }
611 }
612 } while( readcount < count );
613
614 return readcount;
615
616 } /* SK_cd_gets() */
617
618
619 int SK_cd_close(sk_conn_st *condat) {
/* [<][>][^][v][top][bottom][index][help] */
620 return SK_close(condat->sock);
621 } /* SK_cd_close() */
622
623
624 /* print to condat like printf
625
626 by marek
627 */
628 int SK_cd_printf(sk_conn_st *condat, char *txt, ...)
/* [<][>][^][v][top][bottom][index][help] */
629 {
630 #define SKBUFLEN 2047
631 va_list ap;
632 char buffer[SKBUFLEN+1];
633 int len;
634 char *newbuf = NULL;
635 char *finalbuf = buffer; /* points to where the text REALLY is */
636
637 /* vsnprintf returns the number of character it WOULD write if it could.
638 So we assume the buffer to be of adequate size for most cases,
639 and if it isn't, then we allocate to newbuf and call v*printf again
640 */
641 va_start(ap, txt);
642 len = vsnprintf(buffer, SKBUFLEN, txt, ap);
643 va_end(ap);
644
645 if( len > SKBUFLEN ) {
646 dieif(!NOERR(wr_malloc( (void **)& newbuf, len+1)));
647
648 va_start(ap, txt);
649 vsnprintf(newbuf, len, txt, ap);
650 va_end(ap);
651
652 finalbuf = newbuf;
653 }
654 /* terminate */
655 finalbuf[len] = 0;
656
657 /* reuse len */
658 len = SK_cd_puts(condat, finalbuf);
659
660 if(newbuf != NULL) {
661 wr_free(newbuf);
662 }
663
664 return len;
665 }
666
667 /* =========================== watchdog =========================== */
668
669 #define ONCE_INIT 0xABCDEF
670 static pthread_key_t sk_watch_tsd = ONCE_INIT;
671
672 void SK_init(void)
/* [<][>][^][v][top][bottom][index][help] */
673 {
674 /* can be called only once */
675 dieif( sk_watch_tsd != ONCE_INIT );
676 dieif( pthread_key_create( &sk_watch_tsd, NULL) != 0 );
677 }
678
679 /* sk_watchdog signal handler */
680 static void func_sigusr(int n) {
/* [<][>][^][v][top][bottom][index][help] */
681 int *tsd_flag = (int *) pthread_getspecific(sk_watch_tsd);
682
683 ER_dbg_va(FAC_SK, ASP_SK_GEN,"func_sigusr(%d) called", n);
684
685 /* set a thread-specific flag that the handler was invoked */
686
687 pthread_setspecific(sk_watch_tsd, (void *)1 );
688 }
689
690 /* sk_watchdog - started as a separate thread.
691
692 selects on the given socket; discards all input.
693 whenever it sees end of file (socket closed), it
694 * sets a corresponding flag in the condat structure,
695 * kills a thread designated to be killed (by SK_watchkill)
696
697 by marek;
698 */
699 static
700 void *sk_watchdog(void *arg)
/* [<][>][^][v][top][bottom][index][help] */
701 {
702 sk_conn_st *condat = (sk_conn_st *) arg;
703 int nready;
704 int n;
705 fd_set rset;
706 char buff[STR_S];
707 int socket = condat->sock;
708 sigset_t sset;
709 struct sigaction act;
710
711 struct timeval timeout = { 1, 0 }; /* it's a timeout of 1 second */
712
713 FD_ZERO(&rset);
714 FD_SET(socket, &rset);
715
716 sigemptyset(&sset);
717 sigaddset(&sset, SIGUSR1);
718
719 act.sa_handler = func_sigusr;
720 act.sa_flags = 0;
721 dieif(sigaction(SIGUSR1, &act, NULL) != 0);
722
723 /* XXX in fact, it's unblocked already. Should be blocked on startup */
724 dieif(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) != 0);
725
726 /* clear the handler's flag */
727 pthread_setspecific(sk_watch_tsd, NULL);
728
729 /* now ready for signal */
730 pthread_mutex_unlock( & condat->watchmutex );
731
732 /* hey, viva threaded signal handling! There is no way for select
733 to unblock a blocked signal, It must be done by "hand" (above).
734
735 Consequently, every once in a while, the signal will be delivered
736 before the select starts :-/. So, we have to introduce a timeout
737 for select and check if the signal was delivered anyway....aARGH!!!
738
739 This adds a <timeout interval> to unlucky queries, about 0.1% of all.
740 */
741
742 while ((nready=select(socket+1, &rset, NULL, NULL, &timeout))!=-1) {
743
744 ER_dbg_va(FAC_SK, ASP_SK_GEN,"select returned %d", nready);
745
746 /* don't even try to read if we have been killed */
747 if( errno == EINTR || pthread_getspecific(sk_watch_tsd) != NULL ) {
748 break;
749 }
750
751 /* retry if the timeout has triggered */
752 if( nready == 0 ) {
753 continue;
754 }
755
756 /* There was some input or client half of connection was closed */
757 /* Check for the latter */
758 if (( n=read(socket, buff, sizeof(buff))) == 0) {
759 /* Connection was closed by client */
760 /* Now send a cancellation request to the whois thread. */
761 /* mysql thread will be terminated by thread cleanup routine */
762
763 /* set the reason-to-close flag on this connection */
764 condat->rtc |= SK_INTERRUPT;
765
766 /* cancel the thread to be cancelled if defined */
767 if( condat->killthis != 0 ) {
768 pthread_cancel(condat->killthis);
769 /* The only possible error is ESRCH, so we do not care about it*/
770 }
771
772 /* call the function to be called if defined */
773 if( condat->execthis != NULL ) {
774 condat->execthis(condat->execargs);
775 }
776
777 /* quit */
778 break;
779 }
780 /* Otherwise dump input and continue */
781
782 }
783
784 /* Exit the watchdog thread, passing NULL as we don't expect a join */
785 pthread_exit(NULL);
786
787 /* oh yes. Shouldn't compilers _analyze_ library functions ? */
788 return NULL;
789 }
790 /* SK_watchstart
791
792 starts sk_watchdog thread unless already started,
793 and registers its threadid in the condat structure
794
795 dies if watchdog already running
796 */
797 er_ret_t
798 SK_watchstart(sk_conn_st *condat)
/* [<][>][^][v][top][bottom][index][help] */
799 {
800 dieif( condat->watchdog != 0 );
801
802 /* init the mutex in locked state, watchdog will unlock it when
803 it's ready for signal */
804 pthread_mutex_init( & condat->watchmutex, NULL );
805 pthread_mutex_lock( & condat->watchmutex );
806
807 pthread_create(&condat->watchdog, NULL, sk_watchdog, (void *) condat );
808
809 return SK_OK;
810 }
811
812
813 /* SK_watchstop
814
815 stops sk_watchdog thread if it is registered in the connection struct
816 */
817 er_ret_t
818 SK_watchstop(sk_conn_st *condat)
/* [<][>][^][v][top][bottom][index][help] */
819 {
820 void *res;
821
822 if(condat->watchdog > 0) {
823 int ret;
824
825 /* wait until the watchdog is ready for signal */
826 pthread_mutex_lock( & condat->watchmutex );
827
828 ret = pthread_kill(condat->watchdog, SIGUSR1);
829
830 ret = pthread_join(condat->watchdog, &res);
831
832 pthread_mutex_destroy( & condat->watchmutex );
833 condat->watchdog = 0;
834 }
835 return SK_OK;
836 }
837
838 /* SK_watchkill
839
840 sets the threadid of the thread to be killed by watchdog
841 0 means dont kill anything
842 */
843 void
844 SK_watchkill(sk_conn_st *condat, pthread_t killthis)
/* [<][>][^][v][top][bottom][index][help] */
845 {
846 condat->killthis = killthis;
847 }
848
849 void
850 SK_watchexec( sk_conn_st *condat, void *(*function)(void *) , void *args)
/* [<][>][^][v][top][bottom][index][help] */
851 {
852 condat->execthis = function;
853 condat->execargs = args;
854 }
855
856 void
857 SK_watchclear(sk_conn_st *condat)
/* [<][>][^][v][top][bottom][index][help] */
858 {
859 condat->execthis = NULL;
860 condat->execargs = NULL;
861 condat->killthis = 0;
862 }