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