00001
00008 extern "C"
00009 {
00010 #include <sys/times.h>
00011 }
00012
00013 static inline double difftimes(clock_t t1, clock_t t0)
00014 {
00015
00016 return static_cast<double>(t1-t0)/static_cast<double>(sysconf(_SC_CLK_TCK));
00017 }
00018
00019
00020 void Cprocess_clients::process_data_stream_ecm(const connection_waiter& my_connection_waiter)
00021 {
00022 streampos fpos = Recovery_from_file.tellg();
00023 int Number_of_curves = 0;
00024 string s;
00025
00026 srand(time(NULL));
00027
00028 Recovery_from_file >> Number_of_curves;
00029 Recovery_from_file.ignore(1,'\n');
00030
00031 while (Number_of_curves<elcu_Kurven)
00032 {
00033 unix_io_stream daten(my_connection_waiter);
00034
00035 daten >> s;
00036
00037 if (s == "ECM?")
00038 {
00039 int ecm_sigma = rand();
00040 daten << ecm_sigma << " "
00041 << elcu_Phase1 << " "
00042 << elcu_Phase2 << " "
00043 << n << endl;
00044
00045 Number_of_curves++;
00046 cout_network << "elliptic curve #" << Number_of_curves << "/" << elcu_Kurven
00047 << " with sigma=" << ecm_sigma
00048 << " sent to " << peer_info(daten) << endl;
00049
00050
00051 Recovery_to_file.seekp(fpos);
00052 Recovery_to_file << Number_of_curves << endl << flush;
00053 ecm_curves_processed=Number_of_curves;
00054
00055 daten << flush;
00056 continue;
00057 }
00058
00059 if (s == "Faktor(ECM)!")
00060 {
00061 cout_network << "Factor received from " << peer_info(daten) << endl;
00062 int sigma;
00063 mpz_t x;
00064 mpz_init(x);
00065 daten >> sigma >> x;
00066 while (isspace(daten.peek())) daten.get();
00067 string ecm_s = "ecm";
00068 if (daten.peek()!=EOF) daten >> ecm_s;
00069 mpz_gcd(x,x,n);
00070 if (mpz_cmp_ui(x,1)!=0)
00071 {
00072
00073 const unsigned int exponent = mpz_remove(n,n,x);
00074 if (mpz_probab_prime_p(x,probab_prime_checks))
00075 {
00076 cout << x << " is factor." << endl;
00077 if (mpz_sizeinbase(x,10)<28)
00078 {
00079 ostringstream comment;
00080 comment << " [" << ecm_s << "]";
00081 Factorization_to_file << MAL(x,exponent,comment) << flush;
00082 }
00083 else
00084 {
00085 ostringstream comment;
00086 comment << " [" << ecm_s << ",sigma=" << sigma << "]";
00087 Factorization_to_file << MAL(x,exponent,comment) << flush;
00088 }
00089 }
00090 else
00091 {
00092 cout << x << " is a composite factor." << endl;
00093 if (mpz_probab_prime_p(n,probab_prime_checks))
00094 {
00095 if (exponent>1) mpz_pow_ui(x,x,exponent);
00096 mpz_swap(n,x);
00097 cout << x << " is factor. (factorswap)" << endl;
00098 ostringstream comment;
00099 comment << " [" << ecm_s << "/factorswap,sigma=" << sigma << "]";
00100 Factorization_to_file << MAL(x,comment) << flush;
00101 }
00102 else
00103 {
00104 if (mpz_sizeinbase(x,10)<28)
00105 {
00106 ostringstream comment;
00107 comment << " [" << ecm_s << "] [composite]";
00108 Factorization_to_file << MAL(x,exponent,comment) << flush;
00109 }
00110 else
00111 {
00112 ostringstream comment;
00113 comment << " [" << ecm_s << ",sigma=" << sigma << "] [composite]";
00114 Factorization_to_file << MAL(x,exponent,comment) << flush;
00115 }
00116 }
00117 }
00118 }
00119 mpz_clear(x);
00120 daten << flush;
00121
00122 if (mpz_probab_prime_p(n,probab_prime_checks))
00123 {
00124 Factorization_to_file << MAL(n);
00125 cout << "remaining factor: " << n << endl;
00126 cout << "remaining factor is most probably prime!" << endl;
00127 mpz_set_ui(n,1);
00128 }
00129
00130 if ( (mpz_cmp_ui(n,1)==0) || Potenztest(n) )
00131 {
00132 cout << "factorization successfully completed." << endl;
00133 Factorization_to_file << endl;
00134 ExitManager::StopFactorization();
00135 }
00136 tune_parameters(mpz_sizeinbase(n,10));
00137
00138
00139
00140 Recovery_buffer.close();
00141 Recovery_buffer.open(RecoveryFile.c_str(),ios::in|ios::out|ios::trunc);
00142 Recovery_to_file << n << endl;
00143 fpos = Recovery_from_file.tellg();
00144 Recovery_to_file << Number_of_curves << endl << flush;
00145 continue;
00146 }
00147
00148 if (s == QsieveLogon)
00149 {
00150
00151 cerr << "Inadequate request of MPQS parameters from " << peer_info(daten) << endl;
00152 daten << -1 << " " << "please wait until ecm is processed!" << endl;
00153 continue;
00154 }
00155
00156 cerr << "Invalid request \"" << s << "\""
00157 << " from " << peer_info(daten) << endl;
00158 daten << flush;
00159 }
00160 cout << "distributed ECM-Phase (server) completed." << endl;
00161 }
00162
00163
00164
00165
00166 void Cprocess_clients::seek_emergency_handler(istream &in, const streampos pos)
00167 {
00168
00169
00170
00171
00172
00173 cerr << "invalid seek position on istream, trying to resolve..." << endl;
00174
00175
00176
00177
00178 in.clear();
00179 CCriticalSection CriticalSection(ServerMutex,false);
00180 if (CriticalSection.try_enter())
00181 {
00182 DynamicRelations::DynamicRelations_to_file.flush();
00183 CriticalSection.leave();
00184 in.seekg(pos);
00185 if (in.peek()!=EOF) return;
00186 }
00187 else
00188 {
00189
00190
00191 sleep(2); in.seekg(pos);
00192 if (in.peek()!=EOF) return;
00193 #if 1
00194 cerr << "invalid seek position on istream not resolved, trying to flush ostream without obtaining a lock" << endl;
00195
00196
00197
00198
00199 in.clear(); DynamicRelations::DynamicRelations_to_file.flush(); in.seekg(pos);
00200 if (in.peek()!=EOF) return;
00201 #endif
00202 }
00203
00204 throw ios_base::failure("unresolvable invalid seek position on istream");
00205 }
00206
00207 CCriticalSection::Mutex Cprocess_clients::ServerMutex;
00208
00209 void Cprocess_clients::process_data_stream(unix_io_stream &daten, const string client)
00210 {
00211 string s;
00212 daten >> s;
00213
00214 CCriticalSection CriticalSection(ServerMutex,false);
00215
00216
00217
00218
00219
00220 if (s == QsieveLogon)
00221 {
00222 cout_network << "Sending number to factor to " << client << endl;
00223 daten << n << " " << StaticFactorbase::Size() << " "
00224 << Factor_Threshold << " " << LogicalSieveSize << endl;
00225 return;
00226 }
00227
00228 if (s == "ECM?")
00229 {
00230 daten << "-1" << endl;
00231 }
00232
00233 if (s == "Faktor(ECM)!")
00234 {
00235 cout_network << "Factor received from " << client << endl;
00236 int sigma;
00237 mpz_t x;
00238 mpz_init(x);
00239 daten >> sigma >> x;
00240 while (isspace(daten.peek())) daten.get();
00241 string ecm_s = "ecm";
00242 if (daten.peek()!=EOF) daten >> ecm_s;
00243 mpz_gcd(x,x,n);
00244 if (mpz_cmp_ui(x,1)==0)
00245 { mpz_clear(x); return; }
00246
00247 CriticalSection.enter();
00248
00249 if (mpz_cmp_ui(x,1)!=0)
00250 {
00251
00252 const unsigned int exponent = mpz_remove(n,n,x);
00253 if (mpz_probab_prime_p(x,probab_prime_checks))
00254 {
00255 cout << x << " is factor." << endl;
00256 if (mpz_sizeinbase(x,10)<28)
00257 {
00258 ostringstream comment;
00259 comment << " [" << ecm_s << "]";
00260 Factorization_to_file << MAL(x,exponent,comment) << flush;
00261 }
00262 else
00263 {
00264 ostringstream comment;
00265 comment << " [" << ecm_s << ",sigma=" << sigma << "]";
00266 Factorization_to_file << MAL(x,exponent,comment) << flush;
00267 }
00268 }
00269 else
00270 {
00271 cout << x << " is a composite factor." << endl;
00272 if (mpz_sizeinbase(x,10)<28)
00273 {
00274 ostringstream comment;
00275 comment << " [" << ecm_s << "] [composite]";
00276 Factorization_to_file << MAL(x,exponent,comment) << flush;
00277 }
00278 else
00279 {
00280 ostringstream comment;
00281 comment << " [" << ecm_s << ",sigma=" << sigma << "] [composite]";
00282 Factorization_to_file << MAL(x,exponent,comment) << flush;
00283 }
00284 }
00285 }
00286 mpz_clear(x);
00287
00288 if (mpz_probab_prime_p(n,probab_prime_checks))
00289 {
00290 Factorization_to_file << MAL(n);
00291 cout << "remaining factor: " << n << endl;
00292 cout << "remaining factor is most probably prime!" << endl;
00293 mpz_set_ui(n,1);
00294 }
00295
00296 if ( (mpz_cmp_ui(n,1)==0) || Potenztest(n) )
00297 {
00298 cout << "factorization successfully completed." << endl;
00299 Factorization_to_file << endl;
00300 ExitManager::StopFactorization();
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 {
00314
00315
00316
00317 Factorization_to_file << MAL(n) << " [composite]" << endl;
00318 cout << "remaining factor: " << n << endl
00319 << "remaining factor is composite!" << endl;
00320 cout << "factorization needs to be stopped to avoid inconsistent files." << endl
00321 << "please restart factorization with remaining number." << endl;
00322
00323 Factorization_to_file << endl;
00324 ExitManager::StopFactorization();
00325 }
00326
00327 return;
00328 }
00329
00330 if (s=="DynamicFactors?_ab_index")
00331 {
00332
00333 cout_network << "new-style dynamic factor request from " << client << endl;
00334
00335 int i;
00336 daten >> i;
00337 const int start = i;
00338
00339 cout_network << "Sending dynamic factors starting with index " << i
00340 << " to " << client << endl;
00341 for (int j=0; j<20; ++j)
00342 {
00343 const int i_start = i;
00344 while (i<DynamicFactorRelations.monitoredSize())
00345 {
00346
00347
00348 register unsigned int h=DynamicFactorRelations[i];
00349 char c[4];
00350 c[0]=h&0xff; c[1]=(h>>8)&0xff; c[2]=(h>>16)&0xff; c[3]=(h>>24)&0xff;
00351 daten.write(c,4); if (daten.fail()) break;
00352
00353 ++i;
00354 }
00355
00356 pthread_testcancel();
00357 if (i>i_start)
00358 {
00359 daten.flush();
00360 j=0;
00361 }
00362 if (daten.fail()) break;
00363 sleep(2);
00364 pthread_testcancel();
00365 }
00366
00367 if (daten.fail()) cout_network << "dynamic factors thread: transmission failure!" << endl;
00368 else
00369 {
00370 daten.put(0); daten.put(0); daten.put(0); daten.put(0); daten.flush();
00371 }
00372 cout_network << "Dynamic factors from " << start << " to " << i-1
00373 << " sent to " << client << "." << endl;
00374 if (!daten.fail())
00375 {
00376
00377 for(int i=0; i<4; ++i)
00378 if (daten.peek()!=EOF)
00379 {
00380 int h=daten.get();
00381 cerr << "unexpected value (" << h << ") instead of EOF on stream!" << endl;
00382 }
00383 }
00384 cout_network << "Connection to " << client << " closed." << endl;
00385 return;
00386 }
00387
00388 if (s=="DynamicFactors?_ab_fpos")
00389 {
00390 cout_network << "old-style dynamic factor request from " << client << endl;
00391
00392
00393
00394
00395
00396
00397 long long int startfpos;
00398 daten >> startfpos;
00399
00400 CriticalSection.enter();
00401
00402 ostringstream temp_stringstream;
00403 cout_network << "Generating dynamic factors starting with filepos " << startfpos << endl;
00404 const ostream::pos_type saved_fpos = DynamicRelations_to_file.tellp();
00405 DynamicRelations_to_file.seekp(0,ios::end);
00406 const ostream::pos_type fpos_to_transmit = DynamicRelations_to_file.tellp();
00407 DynamicRelations_to_file.seekp(saved_fpos);
00408
00409 #ifdef STL_STREAM_workaround
00410 daten << static_cast<streamoff>(fpos_to_transmit) << " ";
00411 #else
00412 daten << fpos_to_transmit << " ";
00413 #endif
00414
00415 {
00416 CUnlockMutexAtDestruction SLP_Lock(DynamicFactorRelations.SLP_mutex);
00417 DynamicFactorRelations.SLP_mutex.lock();
00418
00419
00420
00421
00422 int prev=0;
00423 for (TDynamicFactorRelations::const_iterator pos=DynamicFactorRelations.begin();
00424 pos != DynamicFactorRelations.end() && pos->sieveable(); ++pos)
00425 #ifdef STL_STREAM_workaround
00426 if (static_cast<streamoff>((*pos).fpos)>=startfpos)
00427 #else
00428 if ((*pos).fpos>=startfpos)
00429 #endif
00430 {
00431 temp_stringstream << (*pos).factor-prev << " ";
00432 prev=(*pos).factor;
00433 }
00434 }
00435
00436 const unsigned int KB = temp_stringstream.str().length()/1024;
00437 cout_network << "Sending dynamic factors starting with fileposition " << startfpos
00438 << " (" << KB << "KB)" <<endl;
00439
00440 CriticalSection.leave();
00441
00442 if (!temp_stringstream.str().empty()) daten << temp_stringstream.str();
00443 if (daten.fail()) cout_network << "dynamic factors thread (old-style): transmission failure!" << endl;
00444 else daten << "-1" << endl;
00445
00446 cout_network << "Connection (old-style) to " << client << " closed." << endl;
00447 return;
00448 }
00449
00450 if (s=="Polynom?")
00451 {
00452 static CCriticalSection::Mutex myPolynomMutex;
00453 int intervall;
00454 daten >> intervall;
00455 cout_network << "Sending new MPQS interval (" << intervall << ")"
00456 << " to " << client << endl;
00457
00458 CCriticalSection CriticalPolynomSection(myPolynomMutex);
00459
00460
00461 Polynom.save(daten);
00462 Polynom.compute_next_polynomial(intervall);
00463 Polynom.save(daten);
00464
00465
00466 streampos fpos = Recovery_to_file.tellp();
00467 Polynom.save(Recovery_to_file);
00468 Recovery_to_file.flush();
00469 Recovery_to_file.seekp(fpos);
00470 return;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 if (s == "NewRelations!")
00503 {
00504 daten.set_TCP_NODELAY();
00505 string ClientAccount = client.substr(0,client.find_first_of(' '));
00506
00507 {
00508
00509 mpz_t received_kN;
00510 mpz_init(received_kN);
00511 daten >> received_kN;
00512 if (daten.fail() || mpz_cmp(received_kN,kN)!=0)
00513 {
00514 daten.clear(daten.rdstate() & ~std::ios::failbit);
00515 daten << "VOID_number!!" << endl;
00516 return;
00517 }
00518 else daten << "proceed" << endl;
00519 mpz_clear(received_kN);
00520
00521 daten >> s;
00522 if (s=="Account:")
00523 {
00524
00525 s=read_restrictedName(daten);
00526 if (s!="")
00527 {
00528 ClientAccount=s;
00529 #ifdef VERBOSE_NOTICE
00530 cout << client << " registered as \"" << ClientAccount << "\"" << endl;
00531 #endif
00532 }
00533 daten >> s;
00534 }
00535 if (s!="RL")
00536 {
00537 cerr << "expected block of relations, but got nonsense!" << endl;
00538 return;
00539 }
00540 }
00541
00542 bool Relationsblock_okay = true;
00543 int received_relations_counter = 0;
00544
00545 statistical_data::AllClientStats_Mutex.lock();
00546 statistical_data::CClientStats &ClientStats
00547 = statistical_data::AllClientStats[ClientAccount];
00548 statistical_data::AllClientStats_Mutex.unlock();
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 ClientStats.PutTimeStamp();
00590
00591 do
00592 {
00593 CriticalSection.leave();
00594
00595
00596
00597
00598
00599 ostringstream os;
00600
00601
00602 daten >> s;
00603 if (s != "G")
00604 {
00605 MARK;
00606 cerr << "error: relation start symbol 'G' expected!" << endl;
00607 #ifdef SAFEMODE
00608 return;
00609 #else
00610 exit(1);
00611 #endif
00612 }
00613
00614 CmpqsFactor factor;
00615 daten >> factor;
00616 os << "G " << setprecision(20) << factor;
00617 while (daten.peek()!='\n')
00618 {
00619 char line[1024];
00620 daten.get(line,sizeof(line),'\n'); os << line;
00621 if (daten.fail())
00622 {
00623 cerr << "stream in failstate for " << client << ", aborting thread." << endl;
00624 return;
00625 }
00626 }
00627 { char c; daten.get(c); os << c; }
00628
00629
00630
00631 daten >> s;
00632
00633 while (s=="Relationsblock_Sync")
00634 {
00635
00636 #ifdef VERBOSE_INFO
00637 cout << "syncing with " << client << ", " << received_relations_counter << " received so far." << endl;
00638 #endif
00639 daten << "synced. " << flush;
00640
00641 daten >> s;
00642 if (daten.fail()) return;
00643 ClientStats.PutTimeStamp();
00644 CriticalSection.enter(); StatusReport(); CriticalSection.leave();
00645 }
00646
00647 received_relations_counter++;
00648
00649 #if 0
00650
00651 CriticalSection.enter();
00652
00653 #else
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677 if (!CriticalSection.try_enter())
00678 {
00679 clock_t Start = times(NULL);
00680 CriticalSection.enter();
00681 clock_t Stop = times(NULL); double w=difftimes(Stop,Start);
00682 if (w>0.04)
00683 cout << "thread " << pthread_self() << ", " << client
00684 << " suspended for " << difftimes(Stop,Start) << " seconds." << endl;
00685 }
00686
00687 #endif
00688
00689
00690 #ifdef SAFEMODE
00691 {
00692
00693 istringstream is(os.str());
00694 if (!CRelation::is_valid(is))
00695 {
00696 #ifdef VERBOSE_WARN
00697 MARK;
00698 cerr << "invalid relation received from " << client << endl;
00699 #endif
00700 Relationsblock_okay=false;
00701 continue;
00702 }
00703 else
00704 {
00705 #ifdef VERBOSE_INFO
00706 cout << "valid relation received from " << client << endl;
00707 #endif
00708 }
00709 }
00710 #endif
00711
00712 ClientStats.increment(factor.Type());
00713 if (factor.IsTypeOf(CmpqsFactor::static_prime))
00714 {
00715
00716
00717 statistical_data::DynamicFactorRating.increment_Hits_at_position(0);
00718 CriticalSection.leave();
00719
00720 istringstream is(os.str());
00721 CRelation* GL = new CRelation();
00722 GL->set_MulticombineData(new CRelation::SMulticombineData);
00723 GL->multi_combine_init();
00724 factor = GL->multi_combine_main(is);
00725
00726 StaticRelations::insert(GL,without_multi_combine_init);
00727 continue;
00728 }
00729 if (factor.IsTypeOf(CmpqsFactor::single_large_prime))
00730 {
00731
00732 TDynamicFactorRelation relation;
00733 relation.factor = factor.int_value();
00734 if (!is_dynamic_factor(relation))
00735 {
00736 relation.fpos=DynamicRelations_to_file.tellp();
00737 DynamicRelations_to_file << os.str();
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747 DynamicFactorRelations.insert(relation);
00748 SpecialRelations::split_by_primefactor(relation.factor);
00749 }
00750 else
00751 {
00752
00753 statistical_data::DynamicFactorRating.increment_Hits_at_position(1);
00754 CriticalSection.leave();
00755
00756 istringstream is(os.str());
00757 CRelation* GL = new CRelation();
00758 GL->set_MulticombineData(new CRelation::SMulticombineData);
00759 GL->multi_combine_init();
00760 factor = GL->multi_combine_main(is);
00761 {
00762 mpz_t x; mpz_init(x);
00763 factor.assign_to_mpz(x);
00764 mpz_mul(GL->Delta,GL->Delta,x); mpz_mod(GL->Delta,GL->Delta,n);
00765 mpz_clear(x);
00766 }
00767 istream *pis = DynamicRelations::IstreamPool::acquire_istream();
00768 GL->multi_combine_main(*pis, relation.fpos);
00769 DynamicRelations::IstreamPool::release_istream(pis);
00770
00771 StaticRelations::insert(GL,without_multi_combine_init);
00772 }
00773 continue;
00774 }
00775 if (factor.IsTypeOf(CmpqsFactor::double_large_prime))
00776 {
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802 SpecialRelations::insert(factor,os.str());
00803 if (is_dynamic_factor(factor.LP1())) SpecialRelations::split_by_primefactor(factor.LP1());
00804 if (is_dynamic_factor(factor.LP2())) SpecialRelations::split_by_primefactor(factor.LP2());
00805 continue;
00806 }
00807
00808 cerr << "Error: Trash or a relation of unknown type has been received!" << endl;
00809 Relationsblock_okay=false;
00810 } while (s=="RL");
00811
00812 CriticalSection.leave();
00813 cout_network << "Block of " << received_relations_counter
00814 << " relations received from " << client << "." << endl;
00815 if (!Relationsblock_okay) daten << "ignoriert!" << flush;
00816 else
00817 if (s=="Relationsblock_Ende") daten << "empfangen." << flush;
00818 else
00819 {
00820 cerr << "could not detect (expected) end of block of relations!" << endl;
00821 daten << "Relationsblock_korrekt_beendet???" << flush;
00822 }
00823 CriticalSection.enter(); StatusReport(); CriticalSection.leave();
00824 return;
00825 }
00826
00827 cerr << "Invalid request \"" << s << "\""
00828 << " from " << client << endl;
00829 }
00830
00831
00832 void* Cprocess_clients::THREAD_process_data_stream(void* arg)
00833 {
00834 ExitManager::register_cancel();
00835 const int communication_socket = *static_cast<int*>(arg);
00836 delete static_cast<int*>(arg);
00837
00838 unix_io_stream *communication_stream = NULL;
00839
00840 try
00841 {
00842 communication_stream = new unix_io_stream(communication_socket);
00843 }
00844 catch (exception &e)
00845 {
00846 cerr << "while constructing caught an exception: " << e.what() << endl;
00847 goto done;
00848 }
00849 catch (...)
00850 {
00851 cerr << "while constructing caught an unknown exception!" << endl;
00852 throw;
00853 }
00854
00855
00856
00857 try
00858 {
00859 process_data_stream(*communication_stream,peer_info(*communication_stream));
00860 }
00861 catch (exception &e)
00862 {
00863 cerr << "Cprocess_clients::THREAD_process_data_stream: caught an exception: " << e.what() << endl;
00864 goto done;
00865 }
00866 catch (...)
00867 {
00868 cerr << "Cprocess_clients::THREAD_process_data_stream: while trying to process data stream caught an unknown exception!" << endl;
00869 throw;
00870 }
00871
00872
00873
00874 try
00875 {
00876 if (!communication_stream->fail()) communication_stream->flush();
00877 }
00878 catch (exception &e)
00879 {
00880 cerr << "caught an exception: " << e.what() << endl;
00881 }
00882 catch (...)
00883 {
00884 cerr << "caught an unknown exception!" << endl;
00885 throw;
00886 }
00887
00888 done:
00889
00890 try
00891 {
00892 delete communication_stream;
00893 }
00894 catch (exception &e)
00895 {
00896 cerr << "while destructing caught an exception: " << e.what() << endl;
00897 }
00898 catch (...)
00899 {
00900 cerr << "while destructing caught an unknown exception!" << endl;
00901 throw;
00902 }
00903
00904 ExitManager::unregister_cancel();
00905 return 0;
00906 }