PageRenderTime 56ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/R2007-03-28/octave-forge/main/parallel/src/pserver.cc

#
C++ | 591 lines | 445 code | 88 blank | 58 comment | 56 complexity | 09fbe9ed9d909075992202777438c393 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, GPL-3.0, LGPL-3.0
  1. /*
  2. Copyright (C) 2002 Hayato Fujiwara
  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; either version 2 of the License, or
  6. (at your option) any later version.
  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. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  14. */
  15. #include <octave/oct.h>
  16. #include "defun-dld.h"
  17. #include "dirfns.h"
  18. #include "error.h"
  19. #include "help.h"
  20. #include "oct-map.h"
  21. #include "systime.h"
  22. #include "ov.h"
  23. #include "oct-obj.h"
  24. #include "utils.h"
  25. #include "oct-env.h"
  26. #include "file-io.h"
  27. #include "sighandlers.h"
  28. #include "parse.h"
  29. #include "cmd-edit.h"
  30. #include "variables.h"
  31. #include "toplev.h"
  32. #include "sysdep.h"
  33. #include "oct-prcstrm.h"
  34. #include "oct-stream.h"
  35. #include "oct-strstrm.h"
  36. #include "oct-iostrm.h"
  37. #include "unwind-prot.h"
  38. #include "input.h"
  39. #include "quit.h"
  40. #include <stdio.h>
  41. #include <sys/types.h>
  42. #include <sys/socket.h>
  43. #include <sys/stat.h>
  44. #include <sys/wait.h>
  45. #include <sys/poll.h>
  46. #include <netinet/in.h>
  47. #include <errno.h>
  48. #include <signal.h>
  49. #include <netdb.h>
  50. #include <unistd.h>
  51. #include <setjmp.h>
  52. #include <netinet/in.h>
  53. #define BUFF_SIZE SSIZE_MAX
  54. static bool quitting_gracefully = false;
  55. // Handle server SIGTERM SIGQUIT
  56. static RETSIGTYPE
  57. sigterm_handler (int /* sig */)
  58. {
  59. int len=118;
  60. char hostname[120],pidname[128];
  61. gethostname(hostname,len);
  62. sprintf(pidname,"/tmp/.octave-%s.pid",hostname);
  63. remove (pidname);
  64. close_files ();
  65. std::cerr << "exiting, " <<hostname <<std::endl;
  66. cleanup_tmp_files ();
  67. exit(0);
  68. }
  69. static RETSIGTYPE
  70. sigchld_handler(int /* sig */)
  71. {
  72. int status;
  73. /* Reap all childrens */
  74. while (waitpid(-1, &status, WNOHANG) > 0)
  75. ;
  76. signal(SIGCHLD, sigchld_handler);
  77. }
  78. // XXX FIXME XXX -- this should really be static, but that causes
  79. // problems on some systems.
  80. std::stack<std::string> octave_atexit_functions;
  81. void
  82. do_octave_atexit_server (void)
  83. {
  84. static bool deja_vu = false;
  85. while (! octave_atexit_functions.empty ())
  86. {
  87. std::string fcn = octave_atexit_functions.top ();
  88. octave_atexit_functions.pop ();
  89. feval (fcn, octave_value_list (), 0);
  90. flush_octave_stdout ();
  91. }
  92. if (! deja_vu)
  93. {
  94. deja_vu = true;
  95. command_editor::restore_terminal_state ();
  96. // XXX FIXME XXX -- is this needed? Can it cause any trouble?
  97. raw_mode (0);
  98. close_files ();
  99. cleanup_tmp_files ();
  100. flush_octave_stdout ();
  101. if (!quitting_gracefully && (interactive || forced_interactive))
  102. std::cout << "\n";
  103. }
  104. }
  105. void
  106. clean_up_and_exit_server (int retval)
  107. {
  108. do_octave_atexit_server ();
  109. exit (retval == EOF ? 0 : retval);
  110. }
  111. int
  112. reval_loop (int sock)
  113. {
  114. // Allow the user to interrupt us without exiting.
  115. int len=0;
  116. char *ev_str;
  117. std::string s;
  118. octave_save_signal_mask ();
  119. if (octave_set_current_context)
  120. {
  121. #if defined (USE_EXCEPTIONS_FOR_INTERRUPTS)
  122. panic_impossible ();
  123. #else
  124. unwind_protect::run_all ();
  125. raw_mode (0);
  126. std::cout << "\n";
  127. octave_restore_signal_mask ();
  128. #endif
  129. }
  130. can_interrupt = true;
  131. octave_catch_interrupts ();
  132. octave_initialized = true;
  133. // The big loop.
  134. char dummy;
  135. read(sock,&dummy,sizeof(char));
  136. int retval,count,r_len,num,fin,nl;
  137. struct pollfd *pollfd;
  138. pollfd=(struct pollfd *)malloc(sizeof(struct pollfd));
  139. pollfd[0].fd=sock;
  140. pollfd[0].events=0;
  141. pollfd[0].events=POLLIN|POLLERR|POLLHUP;
  142. do
  143. {
  144. pollfd[0].revents=0;
  145. num=poll(pollfd,1,-1);
  146. if(num){
  147. if(pollfd[0].revents && (pollfd[0].fd !=0)){
  148. if(pollfd[0].revents&POLLIN){
  149. fin=read(sock,&nl,sizeof(int));
  150. len=ntohl(nl);
  151. if(!fin)
  152. clean_up_and_exit_server (0);
  153. }
  154. if(pollfd[0].revents&POLLERR){
  155. std::cerr <<"Error condition "<<std::endl;
  156. clean_up_and_exit_server (POLLERR);
  157. }
  158. if(pollfd[0].revents&POLLHUP){
  159. std::cerr <<"Hung up "<<std::endl;
  160. clean_up_and_exit_server (POLLHUP);
  161. }
  162. }
  163. }
  164. ev_str=new char[len+1];
  165. count=0;
  166. r_len=BUFF_SIZE;
  167. while(count <len){
  168. if((len-count) < BUFF_SIZE)
  169. r_len=len-count;
  170. count +=read(sock,(char *)((int)ev_str+count),r_len);
  171. }
  172. // read(sock,ev_str,len);
  173. ev_str[len]='\0';
  174. s=(std::string)ev_str;
  175. eval_string(s,false,retval,0);
  176. delete(ev_str);
  177. if (error_state)
  178. {
  179. nl=htonl(error_state);
  180. write(sock,&nl,sizeof(int));
  181. read(sock,&nl,sizeof(int));
  182. // clean_up_and_exit_server (retval);
  183. }
  184. else
  185. {
  186. if (octave_completion_matches_called)
  187. octave_completion_matches_called = false;
  188. else
  189. command_editor::increment_current_command_number ();
  190. }
  191. // Blocking Execution
  192. // write(sock,&error_state,sizeof(error_state));
  193. }
  194. while (retval == 0);
  195. return retval;
  196. }
  197. DEFUN_DLD (pserver,,,
  198. "pserver\n\
  199. \n\
  200. Connect hosts and return sockets.")
  201. {
  202. FILE *pidfile=0;
  203. int ppid,len=118;
  204. char hostname[120],pidname[128],errname[128],bakname[128];
  205. struct stat fstat;
  206. gethostname(hostname,len);
  207. sprintf(pidname,"/tmp/.octave-%s.pid",hostname);
  208. if(stat(pidname,&fstat)==0){
  209. std::cerr << "octave : "<<hostname<<": server already running"<<std::endl;
  210. clean_up_and_exit (1);
  211. }
  212. if (fork())
  213. clean_up_and_exit(0);
  214. /* Touch lock file. */
  215. ppid=getpid();
  216. pidfile = fopen (pidname, "w");
  217. fprintf(pidfile,"%d\n",ppid);
  218. fclose(pidfile);
  219. std::cout <<pidname<<std::endl;
  220. /* */
  221. signal(SIGCHLD, sigchld_handler);
  222. signal(SIGTERM,sigterm_handler);
  223. signal(SIGQUIT,sigterm_handler);
  224. /* Redirect stdin, stdout, and stderr to /dev/null. */
  225. freopen("/dev/null", "r", stdin);
  226. freopen("/dev/null", "w", stdout);
  227. sprintf(errname,"/tmp/octave_error-%s.log",hostname);
  228. if(stat(errname,&fstat)==0){
  229. sprintf(bakname,"/tmp/octave_error-%s.bak",hostname);
  230. rename(errname,bakname);
  231. }
  232. freopen(errname, "w", stderr);
  233. int sock=0,asock=0,dsock=0,dasock=0,pid=0;
  234. struct sockaddr_in *addr,rem_addr;;
  235. addr=(struct sockaddr_in *) calloc(1,sizeof(struct sockaddr_in));
  236. sock=socket(PF_INET,SOCK_STREAM,0);
  237. if(sock==-1){
  238. perror("socket ");
  239. int len=118;
  240. char hostname[120],pidname[128];
  241. gethostname(hostname,len);
  242. sprintf(pidname,".octave-%s.pid",hostname);
  243. remove (pidname);
  244. close_files ();
  245. clean_up_and_exit (1);
  246. }
  247. addr->sin_family=AF_INET;
  248. addr->sin_port=htons(12502);
  249. addr->sin_addr.s_addr=INADDR_ANY;
  250. if(bind(sock,(struct sockaddr *) addr,sizeof(*addr))!=0){
  251. perror("bind ");
  252. int len=118;
  253. char hostname[120],pidname[128];
  254. gethostname(hostname,len);
  255. sprintf(pidname,".octave-%s.pid",hostname);
  256. remove (pidname);
  257. close_files ();
  258. clean_up_and_exit (1);
  259. }
  260. free(addr);
  261. if(listen(sock,1)!=0){
  262. perror("listen ");
  263. clean_up_and_exit (1);
  264. }
  265. dsock=socket(PF_INET,SOCK_STREAM,0);
  266. if(dsock==-1){
  267. perror("socket : ");
  268. exit(-1);
  269. }
  270. addr=(struct sockaddr_in *) calloc(1,sizeof(struct sockaddr_in));
  271. addr->sin_family=AF_INET;
  272. addr->sin_port=htons(12501);
  273. addr->sin_addr.s_addr=INADDR_ANY;
  274. if(bind(dsock,(struct sockaddr *) addr,sizeof(*addr))!=0){
  275. perror("bind : ");
  276. exit(-1);
  277. }
  278. if(listen(dsock,SOMAXCONN)!=0){
  279. perror("listen : ");
  280. exit(-1);
  281. }
  282. free(addr);
  283. int param=1;
  284. socklen_t ol=sizeof(param);
  285. setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&param,ol);
  286. setsockopt(dsock,SOL_SOCKET,SO_REUSEADDR,&param,ol);
  287. int val=1,num_nodes,me,i,j=0,pppid=0,rpppid=0,result=0,nl;
  288. int *sock_v;
  289. char **host_list,rem_name[128];
  290. struct hostent *he;
  291. ol=sizeof(val);
  292. for(;;)
  293. {
  294. asock=accept(sock,0,0);
  295. if(asock==-1){
  296. perror("accept com");
  297. clean_up_and_exit (1);
  298. }
  299. /* Normal production daemon. Fork, and have the child process
  300. the connection. The parent continues listening. */
  301. if((pid=fork())==-1)
  302. {
  303. perror("fork ");
  304. clean_up_and_exit (1);
  305. }
  306. else if(pid==0)
  307. {
  308. close(sock);
  309. signal(SIGCHLD,SIG_DFL);
  310. signal(SIGTERM,SIG_DFL);
  311. signal(SIGQUIT,SIG_DFL);
  312. val=1;
  313. ol=sizeof(val);
  314. setsockopt(asock,SOL_SOCKET,SO_REUSEADDR,&val,ol);
  315. read(asock,&nl,sizeof(int));
  316. num_nodes=ntohl(nl);
  317. read(asock,&nl,sizeof(int));
  318. me=ntohl(nl);
  319. read(asock,&nl,sizeof(int));
  320. pppid=ntohl(nl);
  321. sock_v=(int *)calloc((num_nodes+1)*3,sizeof(int));
  322. host_list=(char **)calloc(num_nodes,sizeof(char *));
  323. for(i=0;i<=num_nodes;i++){
  324. read(asock,&nl,sizeof(int));
  325. len=ntohl(nl);
  326. host_list[i]=(char *)calloc(len,sizeof(char *));
  327. read(asock,host_list[i],len);
  328. }
  329. sprintf(errname,"/tmp/octave_error-%s_%05d.log",hostname,pppid);
  330. if(stat(errname,&fstat)==0){
  331. sprintf(bakname,"/tmp/octave_error-%s_%05d.bak",hostname,pppid);
  332. rename(errname,bakname);
  333. }
  334. freopen(errname, "w", stderr);
  335. for(i=0;i<me;i++){
  336. // recv;
  337. len=sizeof(rem_addr);
  338. while(1){
  339. dasock=accept(dsock,(sockaddr *)&rem_addr,(socklen_t *)&len);
  340. if(dasock==-1){
  341. perror("accept dat ");
  342. exit(-1);
  343. }
  344. int bufsize=BUFF_SIZE;
  345. socklen_t ol;
  346. ol=sizeof(bufsize);
  347. setsockopt(dasock,SOL_SOCKET,SO_SNDBUF,&bufsize,ol);
  348. setsockopt(dasock,SOL_SOCKET,SO_RCVBUF,&bufsize,ol);
  349. bufsize=1;
  350. ol=sizeof(bufsize);
  351. setsockopt(dasock,SOL_SOCKET,SO_REUSEADDR,&bufsize,ol);
  352. //recv pppid
  353. read(dasock,&nl,sizeof(int));
  354. rpppid=ntohl(nl);
  355. //recv name size
  356. read(dasock,&nl,sizeof(int));
  357. len=ntohl(nl);
  358. //recv name
  359. read(dasock,rem_name,len+1);
  360. rem_name[len]='\0';
  361. for(j=0;j<me;j++){
  362. if(strcmp(rem_name,host_list[j])==0){
  363. sock_v[j]=dasock;
  364. result=0;
  365. break;
  366. }else{
  367. result=-1;
  368. }
  369. }
  370. //send result code
  371. if(result==0){
  372. if(pppid==rpppid){
  373. result=0;
  374. nl=htonl(result);
  375. write(dasock,&nl,sizeof(int));
  376. //send endian
  377. nl=htonl(__BYTE_ORDER);
  378. write(dasock,&nl,sizeof(int));
  379. //recv endian
  380. read(sock,&nl,sizeof(int));
  381. sock_v[j+2*(num_nodes+1)]=ntohl(nl);
  382. break;
  383. }
  384. }else{
  385. result=-1;
  386. nl=htonl(result);
  387. write(dasock,&nl,sizeof(int));
  388. close(dasock);
  389. sleep(1);
  390. }
  391. }
  392. }
  393. // close(dsock);
  394. //me
  395. errno=0;
  396. for(i=(me+1);i<=num_nodes;i++){
  397. dsock=-1;
  398. // connect;
  399. dsock=socket(PF_INET,SOCK_STREAM,0);
  400. if(dsock==-1){
  401. perror("socket : ");
  402. exit(-1);
  403. }
  404. addr=(struct sockaddr_in *) calloc(1,sizeof(struct sockaddr_in));
  405. addr->sin_family=AF_INET;
  406. addr->sin_port=htons(12501);
  407. he=gethostbyname(host_list[i]);
  408. if(he == NULL){
  409. error("Unknown host %s",host_list[i]);
  410. }
  411. memcpy(&addr->sin_addr,he->h_addr_list[0],he->h_length);
  412. while(1){
  413. for(j=0;j<10;j++){
  414. if(connect(dsock,(struct sockaddr *)addr,sizeof(*addr))==0){
  415. break;
  416. }else if(errno!=ECONNREFUSED){
  417. perror("connect : ");
  418. exit(-1);
  419. }else {
  420. usleep(5000);
  421. }
  422. }
  423. int bufsize=262144;
  424. socklen_t ol;
  425. ol=sizeof(bufsize);
  426. setsockopt(dsock,SOL_SOCKET,SO_SNDBUF,&bufsize,ol);
  427. setsockopt(dsock,SOL_SOCKET,SO_RCVBUF,&bufsize,ol);
  428. bufsize=1;
  429. ol=sizeof(bufsize);
  430. setsockopt(dsock,SOL_SOCKET,SO_REUSEADDR,&bufsize,ol);
  431. //send pppid
  432. write(dsock,&nl,sizeof(int));
  433. pppid=ntohl(nl);
  434. //send name size
  435. len=strlen(host_list[me]);
  436. nl=htonl(len);
  437. write(dsock,&nl,sizeof(int));
  438. //send name
  439. write(dsock,host_list[me],len+1);
  440. //recv result code
  441. read(dsock,&nl,sizeof(int));
  442. result=ntohl(nl);
  443. if(result==0){
  444. sock_v[i]=dsock;
  445. //recv endian
  446. read(sock,&nl,sizeof(int));
  447. sock_v[i+2*(num_nodes+1)]=ntohl(nl);
  448. //send endian
  449. nl=htonl(__BYTE_ORDER);
  450. write(sock,&nl,sizeof(int));
  451. break;
  452. }else{
  453. close(dsock);
  454. }
  455. }
  456. free(addr);
  457. }
  458. /* for(i=0;i<=num_nodes;i++){
  459. free(host_list[i]);
  460. }
  461. free(host_list);
  462. */
  463. //normal act
  464. install_signal_handlers ();
  465. atexit (do_octave_atexit_server);
  466. char * s;
  467. int stat;
  468. s=(char *)calloc(32,sizeof(char));
  469. sprintf(s,"sockets=[%d,0,%d]",sock_v[0],sock_v[2*(num_nodes+1)]);
  470. eval_string(std::string(s),true,stat);
  471. for(i=1;i<=num_nodes;i++){
  472. sprintf(s,"sockets=[sockets;%d,0,%d]",sock_v[i+2*(num_nodes+1)]);
  473. eval_string(std::string(s),true,stat);
  474. }
  475. interactive = false;
  476. line_editing = false;
  477. // int retval = main_loop ();
  478. char *newdir;
  479. int newdir_len;
  480. read(asock,&nl,sizeof(int));
  481. newdir_len=ntohl(nl);
  482. newdir=(char *)calloc(sizeof(char),newdir_len+1);
  483. read(asock,newdir,newdir_len);
  484. int cd_ok=octave_env::chdir (newdir);
  485. if(cd_ok != true){
  486. octave_env::chdir ("/tmp");
  487. }
  488. int retval = reval_loop(asock);
  489. if (retval == 1 && ! error_state)
  490. retval = 0;
  491. close(asock);
  492. clean_up_and_exit_server (retval);
  493. }
  494. close(asock);
  495. }
  496. close(sock);
  497. exit(-1);
  498. }