~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
/*
17
  Note that we can't have assertion on file descriptors;  The reason for
18
  this is that during mysql shutdown, another thread can close a file
19
  we are working on.  In this case we should just return read errors from
20
  the file descriptior.
21
*/
22
23
#include "vio_priv.h"
24
25
int vio_errno(Vio *vio __attribute__((unused)))
26
{
27
  return socket_errno;		/* On Win32 this mapped to WSAGetLastError() */
28
}
29
30
31
size_t vio_read(Vio * vio, uchar* buf, size_t size)
32
{
33
  size_t r;
34
  DBUG_ENTER("vio_read");
35
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd, (long) buf,
36
                       (uint) size));
37
38
  /* Ensure nobody uses vio_read_buff and vio_read simultaneously */
39
  DBUG_ASSERT(vio->read_end == vio->read_pos);
40
#ifdef __WIN__
41
  r = recv(vio->sd, buf, size,0);
42
#else
43
  errno=0;					/* For linux */
44
  r = read(vio->sd, buf, size);
45
#endif /* __WIN__ */
46
#ifndef DBUG_OFF
47
  if (r == (size_t) -1)
48
  {
49
    DBUG_PRINT("vio_error", ("Got error %d during read",errno));
50
  }
51
#endif /* DBUG_OFF */
52
  DBUG_PRINT("exit", ("%ld", (long) r));
53
  DBUG_RETURN(r);
54
}
55
56
57
/*
58
  Buffered read: if average read size is small it may
59
  reduce number of syscalls.
60
*/
61
62
size_t vio_read_buff(Vio *vio, uchar* buf, size_t size)
63
{
64
  size_t rc;
65
#define VIO_UNBUFFERED_READ_MIN_SIZE 2048
66
  DBUG_ENTER("vio_read_buff");
67
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd, (long) buf,
68
                       (uint) size));
69
70
  if (vio->read_pos < vio->read_end)
71
  {
72
    rc= min((size_t) (vio->read_end - vio->read_pos), size);
73
    memcpy(buf, vio->read_pos, rc);
74
    vio->read_pos+= rc;
75
    /*
76
      Do not try to read from the socket now even if rc < size:
77
      vio_read can return -1 due to an error or non-blocking mode, and
78
      the safest way to handle it is to move to a separate branch.
79
    */
80
  }
81
  else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)
82
  {
83
    rc= vio_read(vio, (uchar*) vio->read_buffer, VIO_READ_BUFFER_SIZE);
84
    if (rc != 0 && rc != (size_t) -1)
85
    {
86
      if (rc > size)
87
      {
88
        vio->read_pos= vio->read_buffer + size;
89
        vio->read_end= vio->read_buffer + rc;
90
        rc= size;
91
      }
92
      memcpy(buf, vio->read_buffer, rc);
93
    }
94
  }
95
  else
96
    rc= vio_read(vio, buf, size);
97
  DBUG_RETURN(rc);
98
#undef VIO_UNBUFFERED_READ_MIN_SIZE
99
}
100
101
102
size_t vio_write(Vio * vio, const uchar* buf, size_t size)
103
{
104
  size_t r;
105
  DBUG_ENTER("vio_write");
106
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd, (long) buf,
107
                       (uint) size));
108
#ifdef __WIN__
109
  r = send(vio->sd, buf, size,0);
110
#else
111
  r = write(vio->sd, buf, size);
112
#endif /* __WIN__ */
113
#ifndef DBUG_OFF
114
  if (r == (size_t) -1)
115
  {
116
    DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno));
117
  }
118
#endif /* DBUG_OFF */
119
  DBUG_PRINT("exit", ("%u", (uint) r));
120
  DBUG_RETURN(r);
121
}
122
123
int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode,
124
		 my_bool *old_mode)
125
{
126
  int r=0;
127
  DBUG_ENTER("vio_blocking");
128
129
  *old_mode= test(!(vio->fcntl_mode & O_NONBLOCK));
130
  DBUG_PRINT("enter", ("set_blocking_mode: %d  old_mode: %d",
131
		       (int) set_blocking_mode, (int) *old_mode));
132
133
#if !defined(__WIN__)
134
#if !defined(NO_FCNTL_NONBLOCK)
135
  if (vio->sd >= 0)
136
  {
137
    int old_fcntl=vio->fcntl_mode;
138
    if (set_blocking_mode)
139
      vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
140
    else
141
      vio->fcntl_mode |= O_NONBLOCK; /* set bit */
142
    if (old_fcntl != vio->fcntl_mode)
143
    {
144
      r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
145
      if (r == -1)
146
      {
147
        DBUG_PRINT("info", ("fcntl failed, errno %d", errno));
148
        vio->fcntl_mode= old_fcntl;
149
      }
150
    }
151
  }
152
#else
153
  r= set_blocking_mode ? 0 : 1;
154
#endif /* !defined(NO_FCNTL_NONBLOCK) */
155
#else /* !defined(__WIN__) */
156
  if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY)
157
  { 
158
    ulong arg;
159
    int old_fcntl=vio->fcntl_mode;
160
    if (set_blocking_mode)
161
    {
162
      arg = 0;
163
      vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
164
    }
165
    else
166
    {
167
      arg = 1;
168
      vio->fcntl_mode |= O_NONBLOCK; /* set bit */
169
    }
170
    if (old_fcntl != vio->fcntl_mode)
171
      r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg);
172
  }
173
  else
174
    r=  test(!(vio->fcntl_mode & O_NONBLOCK)) != set_blocking_mode;
175
#endif /* !defined(__WIN__) */
176
  DBUG_PRINT("exit", ("%d", r));
177
  DBUG_RETURN(r);
178
}
179
180
my_bool
181
vio_is_blocking(Vio * vio)
182
{
183
  my_bool r;
184
  DBUG_ENTER("vio_is_blocking");
185
  r = !(vio->fcntl_mode & O_NONBLOCK);
186
  DBUG_PRINT("exit", ("%d", (int) r));
187
  DBUG_RETURN(r);
188
}
189
190
191
int vio_fastsend(Vio * vio __attribute__((unused)))
192
{
193
  int r=0;
194
  DBUG_ENTER("vio_fastsend");
195
196
#if defined(IPTOS_THROUGHPUT)
197
  {
198
    int tos = IPTOS_THROUGHPUT;
199
    r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos));
200
  }
201
#endif                                    /* IPTOS_THROUGHPUT */
202
  if (!r)
203
  {
204
#ifdef __WIN__
205
    BOOL nodelay= 1;
206
#else
207
    int nodelay = 1;
208
#endif
209
210
    r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
211
                  IF_WIN(const char*, void*) &nodelay,
212
                  sizeof(nodelay));
213
214
  }
215
  if (r)
216
  {
217
    DBUG_PRINT("warning", ("Couldn't set socket option for fast send"));
218
    r= -1;
219
  }
220
  DBUG_PRINT("exit", ("%d", r));
221
  DBUG_RETURN(r);
222
}
223
224
int vio_keepalive(Vio* vio, my_bool set_keep_alive)
225
{
226
  int r=0;
227
  uint opt = 0;
228
  DBUG_ENTER("vio_keepalive");
229
  DBUG_PRINT("enter", ("sd: %d  set_keep_alive: %d", vio->sd, (int)
230
		       set_keep_alive));
231
  if (vio->type != VIO_TYPE_NAMEDPIPE)
232
  {
233
    if (set_keep_alive)
234
      opt = 1;
235
    r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
236
		   sizeof(opt));
237
  }
238
  DBUG_RETURN(r);
239
}
240
241
242
my_bool
243
vio_should_retry(Vio * vio __attribute__((unused)))
244
{
245
  int en = socket_errno;
246
  return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
247
	  en == SOCKET_EWOULDBLOCK);
248
}
249
250
251
my_bool
252
vio_was_interrupted(Vio *vio __attribute__((unused)))
253
{
254
  int en= socket_errno;
255
  return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
256
	  en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
257
}
258
259
260
int vio_close(Vio * vio)
261
{
262
  int r=0;
263
  DBUG_ENTER("vio_close");
264
#ifdef __WIN__
265
  if (vio->type == VIO_TYPE_NAMEDPIPE)
266
  {
267
#if defined(__NT__) && defined(MYSQL_SERVER)
268
    CancelIo(vio->hPipe);
269
    DisconnectNamedPipe(vio->hPipe);
270
#endif
271
    r=CloseHandle(vio->hPipe);
272
  }
273
  else
274
#endif /* __WIN__ */
275
 if (vio->type != VIO_CLOSED)
276
  {
277
    DBUG_ASSERT(vio->sd >= 0);
278
    if (shutdown(vio->sd, SHUT_RDWR))
279
      r= -1;
280
    if (closesocket(vio->sd))
281
      r= -1;
282
  }
283
  if (r)
284
  {
285
    DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno));
286
    /* FIXME: error handling (not critical for MySQL) */
287
  }
288
  vio->type= VIO_CLOSED;
289
  vio->sd=   -1;
290
  DBUG_RETURN(r);
291
}
292
293
294
const char *vio_description(Vio * vio)
295
{
296
  return vio->desc;
297
}
298
299
enum enum_vio_type vio_type(Vio* vio)
300
{
301
  return vio->type;
302
}
303
304
my_socket vio_fd(Vio* vio)
305
{
306
  return vio->sd;
307
}
308
309
my_bool vio_peer_addr(Vio *vio, char *buf, uint16 *port, size_t buflen)
310
{
311
  DBUG_ENTER("vio_peer_addr");
312
  DBUG_PRINT("enter", ("sd: %d", vio->sd));
313
314
  if (vio->localhost)
315
  {
316
    strmov(buf, "127.0.0.1");
317
    *port= 0;
318
  }
319
  else
320
  {
321
    int error;
322
    char port_buf[NI_MAXSERV];
323
    size_socket addrLen = sizeof(vio->remote);
324
    if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
325
                    &addrLen) != 0)
326
    {
327
      DBUG_PRINT("exit", ("getpeername gave error: %d", socket_errno));
328
      DBUG_RETURN(1);
329
    }
330
    vio->addrLen= (int)addrLen;
331
332
    if ((error= getnameinfo((struct sockaddr *)(&vio->remote), 
333
                            addrLen,
334
                            buf, buflen,
335
                            port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
336
    {
337
      DBUG_PRINT("exit", ("getnameinfo gave error: %s", 
338
                          gai_strerror(error)));
339
      DBUG_RETURN(1);
340
    }
341
342
    *port= (uint16)strtol(port_buf, (char **)NULL, 10);
343
344
    /*
345
      A lot of users do not have IPv6 loopback resolving to localhost
346
      correctly setup. Should this exist? No. If we do not do it though
347
      we will be getting a lot of support questions from users who
348
      have bad setups. This code should be removed by say... 2012.
349
        -Brian
350
    */
351
    if (!memcmp(buf, "::ffff:127.0.0.1", sizeof("::ffff:127.0.0.1")))
352
      strmov(buf, "127.0.0.1");
353
  }
354
  DBUG_PRINT("exit", ("addr: %s", buf));
355
  DBUG_RETURN(0);
356
}
357
358
359
/* Return 0 if there is data to be read */
360
361
my_bool vio_poll_read(Vio *vio,uint timeout)
362
{
363
#ifdef __WIN__
364
  int res;
365
  my_socket fd= vio->sd;
366
  fd_set readfds, errorfds;
367
  struct timeval tm;
368
  DBUG_ENTER("vio_poll");
369
  tm.tv_sec= timeout;
370
  tm.tv_usec= 0;
371
  FD_ZERO(&readfds);
372
  FD_ZERO(&errorfds);
373
  FD_SET(fd, &readfds);
374
  FD_SET(fd, &errorfds);
375
  /* The first argument is ignored on Windows, so a conversion to int is OK */
376
  if ((res= select((int) fd, &readfds, NULL, &errorfds, &tm) <= 0))
377
  {
378
    DBUG_RETURN(res < 0 ? 0 : 1);
379
  }
380
  res= FD_ISSET(fd, &readfds) || FD_ISSET(fd, &errorfds);
381
  DBUG_RETURN(!res);
382
#elif defined(HAVE_POLL)
383
  struct pollfd fds;
384
  int res;
385
  DBUG_ENTER("vio_poll");
386
  fds.fd=vio->sd;
387
  fds.events=POLLIN;
388
  fds.revents=0;
389
  if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
390
  {
391
    DBUG_RETURN(res < 0 ? 0 : 1);		/* Don't return 1 on errors */
392
  }
393
  DBUG_RETURN(fds.revents & (POLLIN | POLLERR | POLLHUP) ? 0 : 1);
394
#else
395
  return 0;
396
#endif
397
}
398
399
400
my_bool vio_peek_read(Vio *vio, uint *bytes)
401
{
402
#ifdef __WIN__
403
  int len;
404
  if (ioctlsocket(vio->sd, FIONREAD, &len))
405
    return TRUE;
406
  *bytes= len;
407
  return FALSE;
408
#elif FIONREAD_IN_SYS_IOCTL
409
  int len;
410
  if (ioctl(vio->sd, FIONREAD, &len) < 0)
411
    return TRUE;
412
  *bytes= len;
413
  return FALSE;
414
#else
415
  char buf[1024];
416
  ssize_t res= recv(vio->sd, &buf, sizeof(buf), MSG_PEEK);
417
  if (res < 0)
418
    return TRUE;
419
  *bytes= res;
420
  return FALSE;
421
#endif
422
}
423
424
void vio_timeout(Vio *vio, uint which, uint timeout)
425
{
426
#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)
427
  int r;
428
  DBUG_ENTER("vio_timeout");
429
430
  {
431
#ifdef __WIN__
432
  /* Windows expects time in milliseconds as int */
433
  int wait_timeout= (int) timeout * 1000;
434
#else
435
  /* POSIX specifies time as struct timeval. */
436
  struct timeval wait_timeout;
437
  wait_timeout.tv_sec= timeout;
438
  wait_timeout.tv_usec= 0;
439
#endif
440
441
  r= setsockopt(vio->sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO,
442
                IF_WIN(const char*, const void*)&wait_timeout,
443
                sizeof(wait_timeout));
444
445
  }
446
447
#ifndef DBUG_OFF
448
  if (r != 0)
449
    DBUG_PRINT("error", ("setsockopt failed: %d, errno: %d", r, socket_errno));
450
#endif
451
452
  DBUG_VOID_RETURN;
453
#else
454
/*
455
  Platforms not suporting setting of socket timeout should either use
456
  thr_alarm or just run without read/write timeout(s)
457
*/
458
#endif
459
}
460
461
462
#ifdef __WIN__
463
size_t vio_read_pipe(Vio * vio, uchar* buf, size_t size)
464
{
465
  DWORD length;
466
  DBUG_ENTER("vio_read_pipe");
467
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd, (long) buf,
468
                       (uint) size));
469
470
  if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
471
    DBUG_RETURN(-1);
472
473
  DBUG_PRINT("exit", ("%d", length));
474
  DBUG_RETURN((size_t) length);
475
}
476
477
478
size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size)
479
{
480
  DWORD length;
481
  DBUG_ENTER("vio_write_pipe");
482
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd, (long) buf,
483
                       (uint) size));
484
485
  if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
486
    DBUG_RETURN(-1);
487
488
  DBUG_PRINT("exit", ("%d", length));
489
  DBUG_RETURN((size_t) length);
490
}
491
492
int vio_close_pipe(Vio * vio)
493
{
494
  int r;
495
  DBUG_ENTER("vio_close_pipe");
496
#if defined(__NT__) && defined(MYSQL_SERVER)
497
  CancelIo(vio->hPipe);
498
  DisconnectNamedPipe(vio->hPipe);
499
#endif
500
  r=CloseHandle(vio->hPipe);
501
  if (r)
502
  {
503
    DBUG_PRINT("vio_error", ("close() failed, error: %d",GetLastError()));
504
    /* FIXME: error handling (not critical for MySQL) */
505
  }
506
  vio->type= VIO_CLOSED;
507
  vio->sd=   -1;
508
  DBUG_RETURN(r);
509
}
510
511
512
void vio_ignore_timeout(Vio *vio __attribute__((unused)),
513
			uint which __attribute__((unused)),
514
			uint timeout __attribute__((unused)))
515
{
516
}
517
518
519
#ifdef HAVE_SMEM
520
521
size_t vio_read_shared_memory(Vio * vio, uchar* buf, size_t size)
522
{
523
  size_t length;
524
  size_t remain_local;
525
  char *current_postion;
526
  DBUG_ENTER("vio_read_shared_memory");
527
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %d", vio->sd, (long) buf,
528
                       size));
529
530
  remain_local = size;
531
  current_postion=buf;
532
  do
533
  {
534
    if (vio->shared_memory_remain == 0)
535
    {
536
      HANDLE events[2];
537
      events[0]= vio->event_server_wrote;
538
      events[1]= vio->event_conn_closed;
539
      /*
540
        WaitForMultipleObjects can return next values:
541
         WAIT_OBJECT_0+0 - event from vio->event_server_wrote
542
         WAIT_OBJECT_0+1 - event from vio->event_conn_closed. We can't read
543
		           anything
544
         WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail.  We can't read anything
545
      */
546
      if (WaitForMultipleObjects(2, (HANDLE*)&events,FALSE,
547
                                 vio->net->read_timeout*1000) != WAIT_OBJECT_0)
548
      {
549
        DBUG_RETURN(-1);
550
      };
551
552
      vio->shared_memory_pos = vio->handle_map;
553
      vio->shared_memory_remain = uint4korr((ulong*)vio->shared_memory_pos);
554
      vio->shared_memory_pos+=4;
555
    }
556
557
    length = size;
558
559
    if (vio->shared_memory_remain < length)
560
       length = vio->shared_memory_remain;
561
    if (length > remain_local)
562
       length = remain_local;
563
564
    memcpy(current_postion,vio->shared_memory_pos,length);
565
566
    vio->shared_memory_remain-=length;
567
    vio->shared_memory_pos+=length;
568
    current_postion+=length;
569
    remain_local-=length;
570
571
    if (!vio->shared_memory_remain)
572
    {
573
      if (!SetEvent(vio->event_client_read))
574
        DBUG_RETURN(-1);
575
    }
576
  } while (remain_local);
577
  length = size;
578
579
  DBUG_PRINT("exit", ("%lu", (ulong) length));
580
  DBUG_RETURN(length);
581
}
582
583
584
size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size)
585
{
586
  size_t length, remain, sz;
587
  HANDLE pos;
588
  const uchar *current_postion;
589
  DBUG_ENTER("vio_write_shared_memory");
590
  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %d", vio->sd, (long) buf,
591
                       size));
592
593
  remain = size;
594
  current_postion = buf;
595
  while (remain != 0)
596
  {
597
    if (WaitForSingleObject(vio->event_server_read,
598
                            vio->net->write_timeout*1000) !=
599
        WAIT_OBJECT_0)
600
    {
601
      DBUG_RETURN((size_t) -1);
602
    }
603
604
    sz= (remain > shared_memory_buffer_length ? shared_memory_buffer_length :
605
         remain);
606
607
    int4store(vio->handle_map,sz);
608
    pos = vio->handle_map + 4;
609
    memcpy(pos,current_postion,sz);
610
    remain-=sz;
611
    current_postion+=sz;
612
    if (!SetEvent(vio->event_client_wrote))
613
      DBUG_RETURN((size_t) -1);
614
  }
615
  length = size;
616
617
  DBUG_PRINT("exit", ("%lu", (ulong) length));
618
  DBUG_RETURN(length);
619
}
620
621
622
/**
623
 Close shared memory and DBUG_PRINT any errors that happen on closing.
624
 @return Zero if all closing functions succeed, and nonzero otherwise.
625
*/
626
int vio_close_shared_memory(Vio * vio)
627
{
628
  int error_count= 0;
629
  DBUG_ENTER("vio_close_shared_memory");
630
  if (vio->type != VIO_CLOSED)
631
  {
632
    /*
633
      Set event_conn_closed for notification of both client and server that
634
      connection is closed
635
    */
636
    SetEvent(vio->event_conn_closed);
637
    /*
638
      Close all handlers. UnmapViewOfFile and CloseHandle return non-zero
639
      result if they are success.
640
    */
641
    if (UnmapViewOfFile(vio->handle_map) == 0) 
642
    {
643
      error_count++;
644
      DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed"));
645
    }
646
    if (CloseHandle(vio->event_server_wrote) == 0)
647
    {
648
      error_count++;
649
      DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed"));
650
    }
651
    if (CloseHandle(vio->event_server_read) == 0)
652
    {
653
      error_count++;
654
      DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed"));
655
    }
656
    if (CloseHandle(vio->event_client_wrote) == 0)
657
    {
658
      error_count++;
659
      DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed"));
660
    }
661
    if (CloseHandle(vio->event_client_read) == 0)
662
    {
663
      error_count++;
664
      DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed"));
665
    }
666
    if (CloseHandle(vio->handle_file_map) == 0)
667
    {
668
      error_count++;
669
      DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed"));
670
    }
671
    if (CloseHandle(vio->event_conn_closed) == 0)
672
    {
673
      error_count++;
674
      DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed"));
675
    }
676
  }
677
  vio->type= VIO_CLOSED;
678
  vio->sd=   -1;
679
  DBUG_RETURN(error_count);
680
}
681
#endif /* HAVE_SMEM */
682
#endif /* __WIN__ */