xref: /petsc/src/sys/classes/viewer/impls/socket/send.c (revision 8556b5eb6d24048282742bdd6ce397a5c8264fe5)
1 
2 #include <petscsys.h>
3 
4 #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS)
5 /* Some systems have inconsistent include files that use but do not
6    ensure that the following definitions are made */
7 typedef unsigned char   u_char;
8 typedef unsigned short  u_short;
9 typedef unsigned short  ushort;
10 typedef unsigned int    u_int;
11 typedef unsigned long   u_long;
12 #endif
13 
14 #include <errno.h>
15 #include <ctype.h>
16 #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
17 #include <machine/endian.h>
18 #endif
19 #if defined(PETSC_HAVE_UNISTD_H)
20 #include <unistd.h>
21 #endif
22 #if defined(PETSC_HAVE_SYS_SOCKET_H)
23 #include <sys/socket.h>
24 #endif
25 #if defined(PETSC_HAVE_SYS_WAIT_H)
26 #include <sys/wait.h>
27 #endif
28 #if defined(PETSC_HAVE_NETINET_IN_H)
29 #include <netinet/in.h>
30 #endif
31 #if defined(PETSC_HAVE_NETDB_H)
32 #include <netdb.h>
33 #endif
34 #if defined(PETSC_HAVE_FCNTL_H)
35 #include <fcntl.h>
36 #endif
37 #if defined(PETSC_HAVE_IO_H)
38 #include <io.h>
39 #endif
40 #if defined(PETSC_HAVE_WINSOCK2_H)
41 #include <Winsock2.h>
42 #endif
43 #include <sys/stat.h>
44 #include <../src/sys/classes/viewer/impls/socket/socket.h>
45 
46 #if defined(PETSC_NEED_CLOSE_PROTO)
47 PETSC_EXTERN int close(int);
48 #endif
49 #if defined(PETSC_NEED_SOCKET_PROTO)
50 PETSC_EXTERN int socket(int,int,int);
51 #endif
52 #if defined(PETSC_NEED_SLEEP_PROTO)
53 PETSC_EXTERN int sleep(unsigned);
54 #endif
55 #if defined(PETSC_NEED_CONNECT_PROTO)
56 PETSC_EXTERN int connect(int,struct sockaddr*,int);
57 #endif
58 
59 /*--------------------------------------------------------------*/
60 #undef __FUNCT__
61 #define __FUNCT__ "PetscViewerDestroy_Socket"
62 static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
63 {
64   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data;
65   PetscErrorCode     ierr;
66 
67   PetscFunctionBegin;
68   if (vmatlab->port) {
69 #if defined(PETSC_HAVE_CLOSESOCKET)
70     ierr = closesocket(vmatlab->port);
71 #else
72     ierr = close(vmatlab->port);
73 #endif
74     if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"System error closing socket");
75   }
76   ierr = PetscFree(vmatlab);CHKERRQ(ierr);
77   PetscFunctionReturn(0);
78 }
79 
80 /*--------------------------------------------------------------*/
81 #undef __FUNCT__
82 #define __FUNCT__ "PetscOpenSocket"
83 /*
84     PetscSocketOpen - handles connected to an open port where someone is waiting.
85 
86 .seealso:   PetscSocketListen(), PetscSocketEstablish()
87 */
88 PetscErrorCode  PetscOpenSocket(const char hostname[],int portnum,int *t)
89 {
90   struct sockaddr_in sa;
91   struct hostent     *hp;
92   int                s = 0;
93   PetscErrorCode     ierr;
94   PetscBool          flg = PETSC_TRUE;
95   static int         refcnt = 0;
96 
97   PetscFunctionBegin;
98   if (!(hp=gethostbyname(hostname))) {
99     perror("SEND: error gethostbyname: ");
100     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error open connection to %s",hostname);
101   }
102   ierr = PetscMemzero(&sa,sizeof(sa));CHKERRQ(ierr);
103   ierr = PetscMemcpy(&sa.sin_addr,hp->h_addr_list[0],hp->h_length);CHKERRQ(ierr);
104 
105   sa.sin_family = hp->h_addrtype;
106   sa.sin_port   = htons((u_short) portnum);
107   while (flg) {
108     if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) {
109       perror("SEND: error socket");  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
110     }
111     if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
112 #if defined(PETSC_HAVE_WSAGETLASTERROR)
113       ierr = WSAGetLastError();
114       if (ierr == WSAEADDRINUSE)    (*PetscErrorPrintf)("SEND: address is in use\n");
115       else if (ierr == WSAEALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
116       else if (ierr == WSAEISCONN) {
117         (*PetscErrorPrintf)("SEND: socket already connected\n");
118         Sleep((unsigned) 1);
119       } else if (ierr == WSAECONNREFUSED) {
120         /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
121         Sleep((unsigned) 1);
122       } else {
123         perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
124       }
125 #else
126       if (errno == EADDRINUSE)    (*PetscErrorPrintf)("SEND: address is in use\n");
127       else if (errno == EALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
128       else if (errno == EISCONN) {
129         (*PetscErrorPrintf)("SEND: socket already connected\n");
130         sleep((unsigned) 1);
131       } else if (errno == ECONNREFUSED) {
132         refcnt++;
133         if (refcnt > 5) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SYS,"Connection refused by remote host %s port %d",hostname,portnum);
134         ierr = PetscInfo(0,"Connection refused in attaching socket, trying again\n");CHKERRQ(ierr);
135         sleep((unsigned) 1);
136       } else {
137         perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error");
138       }
139 #endif
140       flg = PETSC_TRUE;
141 #if defined(PETSC_HAVE_CLOSESOCKET)
142       closesocket(s);
143 #else
144       close(s);
145 #endif
146     } else flg = PETSC_FALSE;
147   }
148   *t = s;
149   PetscFunctionReturn(0);
150 }
151 
152 #define MAXHOSTNAME 100
153 #undef __FUNCT__
154 #define __FUNCT__ "PetscSocketEstablish"
155 /*
156    PetscSocketEstablish - starts a listener on a socket
157 
158 .seealso:   PetscSocketListen()
159 */
160 PETSC_INTERN PetscErrorCode PetscSocketEstablish(int portnum,int *ss)
161 {
162   char               myname[MAXHOSTNAME+1];
163   int                s;
164   PetscErrorCode     ierr;
165   struct sockaddr_in sa;
166   struct hostent     *hp;
167 
168   PetscFunctionBegin;
169   ierr = PetscGetHostName(myname,MAXHOSTNAME);CHKERRQ(ierr);
170 
171   ierr = PetscMemzero(&sa,sizeof(struct sockaddr_in));CHKERRQ(ierr);
172 
173   hp = gethostbyname(myname);
174   if (!hp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Unable to get hostent information from system");
175 
176   sa.sin_family = hp->h_addrtype;
177   sa.sin_port   = htons((u_short)portnum);
178 
179   if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error running socket() command");
180 #if defined(PETSC_HAVE_SO_REUSEADDR)
181   {
182     int optval = 1; /* Turn on the option */
183     ierr = setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval));CHKERRQ(ierr);
184   }
185 #endif
186 
187   while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) {
188 #if defined(PETSC_HAVE_WSAGETLASTERROR)
189     ierr = WSAGetLastError();
190     if (ierr != WSAEADDRINUSE) {
191 #else
192     if (errno != EADDRINUSE) {
193 #endif
194       close(s);
195       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error from bind()");
196     }
197   }
198   listen(s,0);
199   *ss = s;
200   return(0);
201 }
202 
203 #undef __FUNCT__
204 #define __FUNCT__ "PetscSocketListen"
205 /*
206    PetscSocketListens - Listens at a socket created with PetscSocketEstablish()
207 
208 .seealso:   PetscSocketEstablish()
209 */
210 PETSC_INTERN PetscErrorCode PetscSocketListen(int listenport,int *t)
211 {
212   struct sockaddr_in isa;
213 #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
214   size_t             i;
215 #else
216   int                i;
217 #endif
218 
219   PetscFunctionBegin;
220   /* wait for someone to try to connect */
221   i = sizeof(struct sockaddr_in);
222   if ((*t = accept(listenport,(struct sockaddr*)&isa,(socklen_t*)&i)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"error from accept()\n");
223   PetscFunctionReturn(0);
224 }
225 
226 #undef __FUNCT__
227 #define __FUNCT__ "PetscViewerSocketOpen"
228 /*@C
229    PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket
230         based server.
231 
232    Collective on MPI_Comm
233 
234    Input Parameters:
235 +  comm - the MPI communicator
236 .  machine - the machine the server is running on,, use NULL for the local machine, use "server" to passively wait for
237              a connection from elsewhere
238 -  port - the port to connect to, use PETSC_DEFAULT for the default
239 
240    Output Parameter:
241 .  lab - a context to use when communicating with the server
242 
243    Level: intermediate
244 
245    Notes:
246    Most users should employ the following commands to access the
247    MATLAB PetscViewers
248 $
249 $    PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
250 $    MatView(Mat matrix,PetscViewer viewer)
251 $
252 $                or
253 $
254 $    PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
255 $    VecView(Vec vector,PetscViewer viewer)
256 
257    Options Database Keys:
258    For use with  PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF,
259    PETSC_VIEWER_SOCKET_() or if
260     NULL is passed for machine or PETSC_DEFAULT is passed for port
261 $    -viewer_socket_machine <machine>
262 $    -viewer_socket_port <port>
263 
264    Environmental variables:
265 +   PETSC_VIEWER_SOCKET_PORT portnumber
266 -   PETSC_VIEWER_SOCKET_MACHINE machine name
267 
268      Currently the only socket client available is MATLAB. See
269      src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
270 
271    Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
272           use PetscViewerBinaryRead/Write/GetDescriptor().
273 
274    Concepts: MATLAB^sending data
275    Concepts: sockets^sending data
276 
277 .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(),
278           PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD,
279           PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(),
280           PetscBinaryViewerGetDescriptor()
281 @*/
282 PetscErrorCode  PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab)
283 {
284   PetscErrorCode ierr;
285 
286   PetscFunctionBegin;
287   ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr);
288   ierr = PetscViewerSetType(*lab,PETSCVIEWERSOCKET);CHKERRQ(ierr);
289   ierr = PetscViewerSocketSetConnection(*lab,machine,port);CHKERRQ(ierr);
290   PetscFunctionReturn(0);
291 }
292 
293 #undef __FUNCT__
294 #define __FUNCT__ "PetscViewerSetFromOptions_Socket"
295 static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscOptionItems *PetscOptionsObject,PetscViewer v)
296 {
297   PetscErrorCode ierr;
298   PetscInt       def = -1;
299   char           sdef[256];
300   PetscBool      tflg;
301 
302   PetscFunctionBegin;
303   /*
304        These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
305     are listed here for the GUI to display
306   */
307   ierr = PetscOptionsHead(PetscOptionsObject,"Socket PetscViewer Options");CHKERRQ(ierr);
308   ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);CHKERRQ(ierr);
309   if (tflg) {
310     ierr = PetscOptionsStringToInt(sdef,&def);CHKERRQ(ierr);
311   } else def = PETSCSOCKETDEFAULTPORT;
312   ierr = PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);CHKERRQ(ierr);
313 
314   ierr = PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);CHKERRQ(ierr);
315   ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);CHKERRQ(ierr);
316   if (!tflg) {
317     ierr = PetscGetHostName(sdef,256);CHKERRQ(ierr);
318   }
319   ierr = PetscOptionsTail();CHKERRQ(ierr);
320   PetscFunctionReturn(0);
321 }
322 
323 /*MC
324    PETSCVIEWERSOCKET - A viewer that writes to a Unix socket
325 
326 
327 .seealso:  PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSC_VIEWER_DRAW_(),PETSC_VIEWER_DRAW_SELF, PETSC_VIEWER_DRAW_WORLD,
328            PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW,
329            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB,
330            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()
331 
332 M*/
333 
334 #undef __FUNCT__
335 #define __FUNCT__ "PetscViewerCreate_Socket"
336 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
337 {
338   PetscViewer_Socket *vmatlab;
339   PetscErrorCode     ierr;
340 
341   PetscFunctionBegin;
342   ierr                   = PetscNewLog(v,&vmatlab);CHKERRQ(ierr);
343   vmatlab->port          = 0;
344   v->data                = (void*)vmatlab;
345   v->ops->destroy        = PetscViewerDestroy_Socket;
346   v->ops->flush          = 0;
347   v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
348 
349   /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
350   ierr                   = PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);CHKERRQ(ierr);
351   PetscFunctionReturn(0);
352 }
353 
354 #undef __FUNCT__
355 #define __FUNCT__ "PetscViewerSocketSetConnection"
356 /*@C
357       PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
358              viewer is to use
359 
360   Logically Collective on PetscViewer
361 
362   Input Parameters:
363 +   v - viewer to connect
364 .   machine - host to connect to, use NULL for the local machine,use "server" to passively wait for
365              a connection from elsewhere
366 -   port - the port on the machine one is connecting to, use PETSC_DEFAULT for default
367 
368     Level: advanced
369 
370 .seealso: PetscViewerSocketOpen()
371 @*/
372 PetscErrorCode  PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port)
373 {
374   PetscErrorCode     ierr;
375   PetscMPIInt        rank;
376   char               mach[256];
377   PetscBool          tflg;
378   PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)v->data;
379 
380   PetscFunctionBegin;
381   /* PetscValidLogicalCollectiveInt(v,port,3); not a PetscInt */
382   if (port <= 0) {
383     char portn[16];
384     ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);CHKERRQ(ierr);
385     if (tflg) {
386       PetscInt pport;
387       ierr = PetscOptionsStringToInt(portn,&pport);CHKERRQ(ierr);
388       port = (int)pport;
389     } else port = PETSCSOCKETDEFAULTPORT;
390   }
391   if (!machine) {
392     ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);CHKERRQ(ierr);
393     if (!tflg) {
394       ierr = PetscGetHostName(mach,256);CHKERRQ(ierr);
395     }
396   } else {
397     ierr = PetscStrncpy(mach,machine,256);CHKERRQ(ierr);
398   }
399 
400   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);CHKERRQ(ierr);
401   if (!rank) {
402     ierr = PetscStrcmp(mach,"server",&tflg);CHKERRQ(ierr);
403     if (tflg) {
404       int listenport;
405       ierr = PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);CHKERRQ(ierr);
406       ierr = PetscSocketEstablish(port,&listenport);CHKERRQ(ierr);
407       ierr = PetscSocketListen(listenport,&vmatlab->port);CHKERRQ(ierr);
408       close(listenport);
409     } else {
410       ierr = PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);CHKERRQ(ierr);
411       ierr = PetscOpenSocket(mach,port,&vmatlab->port);CHKERRQ(ierr);
412     }
413   }
414   PetscFunctionReturn(0);
415 }
416 
417 /* ---------------------------------------------------------------------*/
418 /*
419     The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
420   is attached to a communicator, in this case the attribute is a PetscViewer.
421 */
422 static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;
423 
424 
425 #undef __FUNCT__
426 #define __FUNCT__ "PETSC_VIEWER_SOCKET_"
427 /*@C
428      PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.
429 
430      Collective on MPI_Comm
431 
432      Input Parameter:
433 .    comm - the MPI communicator to share the socket PetscViewer
434 
435      Level: intermediate
436 
437    Options Database Keys:
438    For use with the default PETSC_VIEWER_SOCKET_WORLD or if
439     NULL is passed for machine or PETSC_DEFAULT is passed for port
440 $    -viewer_socket_machine <machine>
441 $    -viewer_socket_port <port>
442 
443    Environmental variables:
444 +   PETSC_VIEWER_SOCKET_PORT portnumber
445 -   PETSC_VIEWER_SOCKET_MACHINE machine name
446 
447      Notes:
448      Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return
449      an error code.  The socket PetscViewer is usually used in the form
450 $       XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm));
451 
452      Currently the only socket client available is MATLAB. See
453      src/dm/da/examples/tests/ex12.c and ex12.m for an example of usage.
454 
455      Connects to a waiting socket and stays connected until PetscViewerDestroy() is called.
456 
457      Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for communicating with the MATLAB engine.
458 
459 .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(),
460           PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(),
461           PetscViewerBinaryWriteStringArray(), PetscBinaryViewerGetDescriptor(), PETSC_VIEWER_MATLAB_()
462 @*/
463 PetscViewer  PETSC_VIEWER_SOCKET_(MPI_Comm comm)
464 {
465   PetscErrorCode ierr;
466   PetscBool      flg;
467   PetscViewer    viewer;
468   MPI_Comm       ncomm;
469 
470   PetscFunctionBegin;
471   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
472   if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) {
473     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0);
474     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
475   }
476   ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Socket_keyval,(void**)&viewer,(int*)&flg);
477   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
478   if (!flg) { /* PetscViewer not yet created */
479     ierr = PetscViewerSocketOpen(ncomm,0,0,&viewer);
480     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
481     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
482     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
483     ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer);
484     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
485   }
486   ierr = PetscCommDestroy(&ncomm);
487   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
488   PetscFunctionReturn(viewer);
489 }
490 
491