~noskcaj/ubuntu/saucy/xinetd/2.3.15

« back to all changes in this revision

Viewing changes to xinetd/retry.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Seyrat
  • Date: 2004-04-18 13:33:57 UTC
  • Revision ID: james.westby@ubuntu.com-20040418133357-czeqeju37433xvdd
Tags: upstream-2.3.13
ImportĀ upstreamĀ versionĀ 2.3.13

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (c) Copyright 1992 by Panagiotis Tsirigotis
 
3
 * (c) Sections Copyright 1998-2001 by Rob Braun
 
4
 * All rights reserved.  The file named COPYRIGHT specifies the terms 
 
5
 * and conditions for redistribution.
 
6
 */
 
7
 
 
8
 
 
9
#include "config.h"
 
10
#include <sys/time.h>
 
11
#include <syslog.h>
 
12
 
 
13
#include "pset.h"
 
14
#include "retry.h"
 
15
#include "state.h"
 
16
#include "main.h"
 
17
#include "server.h"
 
18
#include "service.h"
 
19
#include "connection.h"
 
20
#include "xconfig.h"
 
21
#include "msg.h"
 
22
#include "sconf.h"
 
23
#include "xtimer.h"
 
24
 
 
25
static int retry_timer_running ;
 
26
static void cancel_retry(struct server * serp );
 
27
static void stop_retry_timer(void) ;
 
28
static void start_retry_timer(void) ;
 
29
 
 
30
 
 
31
/*
 
32
 * Attempt to start all servers in the retry table
 
33
 */
 
34
static void server_retry(void)
 
35
{
 
36
   unsigned          servers_started = 0 ;
 
37
   unsigned          u ;
 
38
   const char       *func = "server_retry" ;
 
39
 
 
40
   for ( u = 0 ; u < pset_count( RETRIES( ps ) ) ; u++ )
 
41
   {
 
42
      struct server *retry = SERP( pset_pointer( RETRIES( ps ), u ) ) ;
 
43
      struct service *sp = SERVER_SERVICE( retry ) ;
 
44
      connection_s *cp = SERVER_CONNECTION( retry ) ;
 
45
 
 
46
      /*
 
47
       * Drop the retry if access control fails or we have
 
48
       * a memory allocation problem
 
49
       */
 
50
      if ( svc_parent_access_control( sp, cp ) == FAILED ||
 
51
         svc_child_access_control (sp, cp) == FAILED ||
 
52
         pset_add( SERVERS( ps ), retry ) == NULL )
 
53
      {
 
54
         cancel_retry( retry ) ;
 
55
         pset_pointer( RETRIES( ps ), u ) = NULL ;
 
56
         continue ;
 
57
      }
 
58
 
 
59
      if ( server_start( retry ) == OK )
 
60
      {
 
61
         servers_started++ ;
 
62
         SVC_DEC_RETRIES( sp ) ;
 
63
         if ( !SVC_WAITS( sp ) )
 
64
            CONN_CLOSE( cp ) ;
 
65
         pset_pointer( RETRIES( ps ), u ) = NULL ;
 
66
         continue ;
 
67
      }
 
68
      else
 
69
      {
 
70
         pset_remove( SERVERS( ps ), retry ) ;
 
71
         if ( SERVER_FORKLIMIT( retry ) )
 
72
         {
 
73
            /*
 
74
             * give up retrying
 
75
             */
 
76
            msg( LOG_ERR, func,
 
77
               "service %s: too many consecutive fork failures", SVC_ID(sp) ) ;
 
78
            svc_log_failure( sp, cp, AC_FORK ) ;
 
79
            cancel_retry( retry ) ;
 
80
            pset_pointer( RETRIES( ps ), u ) = NULL ;
 
81
            continue ;
 
82
         }
 
83
         else
 
84
         {
 
85
            if ( debug.on )
 
86
               msg( LOG_DEBUG, func,
 
87
                  "fork failed for service %s. Retrying...", SVC_ID( sp ) ) ;
 
88
         }
 
89
      }
 
90
   }
 
91
 
 
92
   pset_compact( RETRIES( ps ) ) ;
 
93
 
 
94
   if ( debug.on )
 
95
      msg( LOG_DEBUG, func,
 
96
         "%d servers started, %d left to retry",
 
97
            servers_started, pset_count( RETRIES( ps ) ) ) ;
 
98
 
 
99
   /* If there's more, start another callback */
 
100
   if ( pset_count( RETRIES( ps ) ) > 0 ) {
 
101
      if ((retry_timer_running=xtimer_add(server_retry, RETRY_INTERVAL)) == -1)
 
102
      {
 
103
         msg( LOG_ERR, func, "xtimer_add: %m" ) ;
 
104
         retry_timer_running = 0;
 
105
      }
 
106
   }
 
107
   else
 
108
      retry_timer_running = 0;
 
109
}
 
110
 
 
111
 
 
112
/*
 
113
 * Schedule a retry by inserting the struct server in the retry table
 
114
 * and starting the timer if necessary
 
115
 */
 
116
status_e schedule_retry( struct server *serp )
 
117
{
 
118
   struct service *sp = SERVER_SERVICE( serp ) ;
 
119
   const char *func = "schedule_retry" ;
 
120
 
 
121
   if ( pset_add( RETRIES( ps ), serp ) == NULL )
 
122
   {
 
123
      out_of_memory( func ) ;
 
124
      return( FAILED ) ;
 
125
   }
 
126
   SVC_INC_RETRIES( sp ) ;
 
127
   start_retry_timer() ;
 
128
   if ( debug.on )
 
129
      msg( LOG_DEBUG, func, "Scheduled retry attempt for %s", SVC_ID( sp ) ) ;
 
130
   return( OK ) ;
 
131
}
 
132
 
 
133
 
 
134
/*
 
135
 * This function should not be called for servers that correspond to
 
136
 * services not in the service table because server_release will result
 
137
 * in releasing all memory associated with the service (since the ref
 
138
 * count will drop to 0).
 
139
 */
 
140
static void cancel_retry( struct server *serp )
 
141
{
 
142
   struct service *sp = SERVER_SERVICE( serp ) ;
 
143
 
 
144
   conn_free( SERVER_CONNECTION( serp ), 1 ) ;
 
145
   SVC_DEC_RETRIES( sp ) ;
 
146
   server_release( serp ) ;
 
147
}
 
148
 
 
149
 
 
150
 
 
151
/*
 
152
 * Cancel all retry attempts for the specified service
 
153
 */
 
154
void cancel_service_retries( struct service *sp )
 
155
{
 
156
   unsigned u ;
 
157
   const char *func = "cancel_service_retries" ;
 
158
 
 
159
   if ( SVC_RETRIES( sp ) == 0 )
 
160
      return ;
 
161
 
 
162
   u = 0 ;
 
163
   while ( u < pset_count( RETRIES( ps ) ) )
 
164
   {
 
165
      struct server *serp ;
 
166
 
 
167
      serp = SERP( pset_pointer( RETRIES( ps ), u ) ) ;
 
168
      if ( SERVER_SERVICE( serp ) == sp )
 
169
      {
 
170
         msg( LOG_NOTICE, func,
 
171
            "dropping retry attempt for service %s", SVC_ID( sp ) ) ;
 
172
         cancel_retry( serp ) ;
 
173
         pset_remove_index( RETRIES( ps ), u ) ;
 
174
         continue ;
 
175
      }
 
176
      u++ ;
 
177
   }
 
178
 
 
179
   if ( pset_count( RETRIES( ps ) ) == 0 )
 
180
      stop_retry_timer() ;
 
181
}
 
182
 
 
183
 
 
184
static void start_retry_timer(void)
 
185
{
 
186
   const char *func = "start_retry_timer" ;
 
187
 
 
188
   /*
 
189
    * Enable timer if necessary.
 
190
    */
 
191
 
 
192
   if ( retry_timer_running == 0 )
 
193
      if((retry_timer_running=xtimer_add(server_retry, RETRY_INTERVAL)) == -1 ){
 
194
         msg( LOG_ERR, func, "xtimer_add: %m" ) ;
 
195
         retry_timer_running = 0;
 
196
      }
 
197
}
 
198
 
 
199
 
 
200
static void stop_retry_timer(void)
 
201
{
 
202
   if ( retry_timer_running != 0)
 
203
   {
 
204
      xtimer_remove(retry_timer_running);
 
205
      retry_timer_running = 0 ;
 
206
   }
 
207
}
 
208