Failed to set socket option error in Samba 2.0.6/Solaris 7 --
finally some luck
David Collier-Brown
davecb at canada.sun.com
Thu Apr 27 12:54:03 GMT 2000
For the team: Eric had suspicious "Failed to set socket option
SO_KEEPALIVE"
messages, that appeared to be an impossible condition: an fd that
was invalid.
We added debugging statements and tracked it down this far,
and would like suggestions as to why we're seeing failures, then
successes.
If this discussion isn't suitable for samba-technical, please say!
--dave
Eric Boehm wrote:
> Here's the error!
>
> [2000/04/26 09:36:37, 3] smbd/server.c:reload_services(322)
> Client
Ok, the code at line 322 is:
{
extern int Client;
if (Client != -1) {
set_socket_options(Client,"SO_KEEPALIVE");
set_socket_options(Client,user_socket_options);
}
}
So the Client variable is the one we'e interested in, an it
shows as being set as follows: (this is from cscope)
File Function Line
1 util_sock.c <global> 36 int Client = -1;
2 clientutil.c cli_send_session_request 375 Client =
open_socket_out(SOCK_STREAM,
&dest_ip, port,
LONG_CONNECT_TIMEOUT);
3 clientutil.c cli_open_sockets 938 Client =
open_socket_out(SOCK_STREAM,
&dest_ip, port,
LONG_CONNECT_TIMEOUT);
4 util_sock.c close_sockets 191 Client = -1;
5 process.c receive_message_or_smb 170 FD_SET(Client,&fds);
6 server.c open_sockets_inetd 78 Client = dup(0);
7 server.c open_sockets 214 Client =
accept(s,&addr,&in_addrlen);
The next line of the log says we're in util_sock.c...
> [2000/04/26 09:36:37, 10] lib/util_sock.c:set_socket_options(106)
> in set_socket_options(8, SO_KEEPALIVE)
> [2000/04/26 09:36:37, 0] lib/util_sock.c:set_socket_options(148)
> Failed to set socket option SO_KEEPALIVE (Error Bad file number)
And that takes us back to the place where we know the fd (Client) is
invalid.
Let's look at reload_services in detail:
----
BOOL reload_services(BOOL test)
{
BOOL ret;
if (lp_loaded()) {
pstring fname;
pstrcpy(fname,lp_configfile());
if (file_exist(fname,NULL) &&
!strcsequal(fname,servicesf)) {
pstrcpy(servicesf,fname);
test = False;
}
}
reopen_logs();
if (test && !lp_file_list_changed())
return(True);
lp_killunused(conn_snum_used);
ret = lp_load(servicesf,False,False,True);
load_printers();
/* perhaps the config filename is now set */
if (!test)
reload_services(True);
reopen_logs();
load_interfaces();
{
extern int Client;
if (Client != -1) {
set_socket_options(Client,"SO_KEEPALIVE");
set_socket_options(Client,user_socket_options);
}
}
--
and we blow up here. That means Client is set to something other
than -1, and whatever that is, it's not a valid fd, as indicated by
the string of falures which follow:
> [2000/04/26 09:36:37, 3] smbd/server.c:reload_services(324)
> Client
> [2000/04/26 09:36:37, 10] lib/util_sock.c:set_socket_options(106)
> in set_socket_options(8, TCP_NODELAY SO_KEEPALIVE SO_SNDBUF=32768 SO_RCVBUF=32768)
> [2000/04/26 09:36:37, 0] lib/util_sock.c:set_socket_options(148)
> Failed to set socket option TCP_NODELAY (Error Bad file number)
> [2000/04/26 09:36:37, 0] lib/util_sock.c:set_socket_options(148)
> Failed to set socket option SO_KEEPALIVE (Error Bad file number)
> [2000/04/26 09:36:37, 0] lib/util_sock.c:set_socket_options(148)
> Failed to set socket option SO_SNDBUF (Error Bad file number)
> [2000/04/26 09:36:37, 0] lib/util_sock.c:set_socket_options(148)
> Failed to set socket option SO_RCVBUF (Error Bad file number)
After this string of errors, we then go into a string of successes!
We call open_sockets from smbd/server.c at line 214
----------
> [2000/04/26 09:36:37, 3] smbd/server.c:open_sockets(240)
> Client
> [2000/04/26 09:36:37, 10] lib/util_sock.c:set_socket_options(106)
> in set_socket_options(8, SO_KEEPALIVE)
> [2000/04/26 09:36:37, 3] smbd/server.c:open_sockets(242)
> Client
> [2000/04/26 09:36:37, 10] lib/util_sock.c:set_socket_options(106)
> in set_socket_options(8, TCP_NODELAY SO_KEEPALIVE SO_SNDBUF=32768 SO_RCVBUF=32768)
--
Let's look for asignments to Client in server code: there's one at
open_sockets, line 214 of server.c.
---
static BOOL open_sockets(BOOL is_daemon,int port)
...many line skipped...
/* now accept incoming connections - forking a new process
for each incoming connection */
DEBUG(2,("waiting for a connection\n"));
while (1) {
fd_set lfds;
int num;
memcpy((char *)&lfds, (char *)&listen_set,
sizeof(listen_set));
num = sys_select(FD_SETSIZE,&lfds,NULL);
if (num == -1 && errno == EINTR)
continue;
/* check if we need to reload services */
check_reload(time(NULL));
/* Find the sockets that are read-ready -
accept on these. */
for( ; num > 0; num--) {
struct sockaddr addr;
int in_addrlen = sizeof(addr);
s = -1;
for(i = 0; i < num_interfaces; i++) {
if(FD_ISSET(fd_listenset[i],&lfds)) {
s = fd_listenset[i];
/* Clear this so we don't look
at it again. */
FD_CLR(fd_listenset[i],&lfds);
break;
}
}
--line 214----> Client = accept(s,&addr,&in_addrlen);
At this point, if "s" is a valid fd, Client will be a valid fd...
if (Client == -1 && errno == EINTR)
continue;
if (Client == -1) {
DEBUG(0,("open_sockets: accept: %s\n",
strerror(errno)));
continue;
}
And if it isn't, we'd get the error above!
if (Client != -1 && fork()==0) {
/* Child code ... */
/* close the listening socket(s) */
for(i = 0; i < num_interfaces; i++)
close(fd_listenset[i]);
/* close our standard file
descriptors */
close_low_fds();
am_parent = 0;
set_socket_options(Client,"SO_KEEPALIVE");
set_socket_options(Client,user_socket_options);
---
and this is where we now succeed.
Client is now set to something sane, and operates properly,
as shown fromthe logs of log.ipllserver3a, matching timestamp
09:36:37.
>
> [2000/04/26 09:36:37, 6] param/loadparm.c:lp_file_list_changed(1855)
> lp_file_list_changed()
> file /usr/local/samba/lib/smb.conf -> /usr/local/samba/lib/smb.conf last mod_time: Wed Apr 26 08:36:05 2000
...skip...
> [2000/04/26 09:36:37, 6] lib/util_sock.c:write_socket(557)
> write_socket(8,4)
> [2000/04/26 09:36:37, 6] lib/util_sock.c:write_socket(560)
> write_socket(8,4) wrote 4
> [2000/04/26 09:36:48, 10] lib/util_sock.c:read_smb_length_return_keepalive(599)
> got smb length of 170
...and so on
I initiallu speculated that a client was failing between the accept
and the setsockopts, but this isn't the case.
The code above implies that "Client" isn't set to anything plausible
in reload_services. Sinc it's part of server.c, but not
part iof the cleint startup stuff, I wonder if
it should be trying to set the client's fd options at all.
It's only called by server and nmbd code...
---
Functions calling this function: reload_services
File Function Line
1 nmbd.c reload_services 290 reload_services( True );
2 nmbd.c process 477 reload_services( True );
3 nmbd.c main 760 if ( !reload_services(False) )
4 nmbd.c main 768 reload_services( True );
5 negprot.c reply_negprot 394 reload_services(True);
6 negprot.c reply_negprot 425 reload_services(True);
7 process.c check_reload 835 reload_services(True);
8 reply.c reply_special 122 reload_services(True);
9 reply.c reply_sesssetup_and_X 854 reload_services(True);
0 server.c reload_services 308 reload_services(True);
1 server.c main 656 if (!reload_services(False))
2 server.c main 742 reload_services(True);
---
Eric, can you comment out this block of code in reload_services,
please?
Experts, can you recollect a reason we try to set socket options
this far away from the accept call? We do it safely nearby in the
open_sockets code...
--dave
--
David Collier-Brown, | Always do right. This will gratify some people
185 Ellerslie Ave., | and astonish the rest. -- Mark Twain
Willowdale, Ontario | //www.oreilly.com/catalog/samba/author.html
Work: (905) 415-2849 Home: (416) 223-8968 Email: davecb at canada.sun.com
More information about the samba-technical
mailing list