Mercurial > hg > piper-cpp
comparison vamp-server/simple-server.cpp @ 138:b01dac674beb
Discard stdout output that occurs in between our own outputs (e.g. from plugin)
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Thu, 12 Jan 2017 08:49:26 +0000 |
parents | 9da826f812cb |
children | 807a0a43096e |
comparison
equal
deleted
inserted
replaced
137:1902e6db5b61 | 138:b01dac674beb |
---|---|
55 #else | 55 #else |
56 #include <unistd.h> | 56 #include <unistd.h> |
57 static int pid = getpid(); | 57 static int pid = getpid(); |
58 #endif | 58 #endif |
59 | 59 |
60 // for _setmode stuff | 60 // for _setmode stuff and _dup |
61 #ifdef _WIN32 | 61 #ifdef _WIN32 |
62 #include <io.h> | 62 #include <io.h> |
63 #include <fcntl.h> | 63 #include <fcntl.h> |
64 #endif | |
65 | |
66 // for dup, open etc | |
67 #ifndef _WIN32 | |
68 #include <fcntl.h> | |
69 #include <unistd.h> | |
64 #endif | 70 #endif |
65 | 71 |
66 using namespace std; | 72 using namespace std; |
67 using namespace json11; | 73 using namespace json11; |
68 using namespace piper_vamp; | 74 using namespace piper_vamp; |
102 else exit(2); | 108 else exit(2); |
103 } | 109 } |
104 | 110 |
105 static CountingPluginHandleMapper mapper; | 111 static CountingPluginHandleMapper mapper; |
106 | 112 |
113 // We write our output to stdout, but want to ensure that the plugin | |
114 // doesn't write anything itself. To do this we open a null file | |
115 // descriptor and dup2() it into place of stdout in the gaps between | |
116 // our own output activity. | |
117 | |
118 static int normalFd = -1; | |
119 static int suspendedFd = -1; | |
120 | |
121 static void initFds(bool binary) | |
122 { | |
123 #ifdef _WIN32 | |
124 if (binary) { | |
125 int result = _setmode(0, _O_BINARY); | |
126 if (result == -1) { | |
127 throw runtime_error("Failed to set binary mode on stdin"); | |
128 } | |
129 result = _setmode(1, _O_BINARY); | |
130 if (result == -1) { | |
131 throw runtime_error("Failed to set binary mode on stdout"); | |
132 } | |
133 } | |
134 normalFd = _dup(1); | |
135 suspendedFd = _open("NUL", _O_WRONLY); | |
136 #else | |
137 normalFd = dup(1); | |
138 suspendedFd = open("/dev/null", O_WRONLY); | |
139 #endif | |
140 | |
141 if (normalFd < 0 || suspendedFd < 0) { | |
142 throw runtime_error("Failed to initialise fds for stdio suspend/resume"); | |
143 } | |
144 } | |
145 | |
146 static void suspendOutput() | |
147 { | |
148 #ifdef _WIN32 | |
149 _dup2(suspendedFd, 1); | |
150 #else | |
151 dup2(suspendedFd, 1); | |
152 #endif | |
153 } | |
154 | |
155 static void resumeOutput() | |
156 { | |
157 #ifdef _WIN32 | |
158 _dup2(normalFd, 1); | |
159 #else | |
160 dup2(normalFd, 1); | |
161 #endif | |
162 } | |
163 | |
107 static RequestOrResponse::RpcId | 164 static RequestOrResponse::RpcId |
108 readId(const piper::RpcRequest::Reader &r) | 165 readId(const piper::RpcRequest::Reader &r) |
109 { | 166 { |
110 int number; | 167 int number; |
111 string tag; | 168 string tag; |
274 break; | 331 break; |
275 case RRType::NotValid: | 332 case RRType::NotValid: |
276 break; | 333 break; |
277 } | 334 } |
278 } | 335 } |
279 | 336 |
280 cout << j.dump() << endl; | 337 cout << j.dump() << endl; |
281 } | 338 } |
282 | 339 |
283 void | 340 void |
284 writeExceptionJson(const std::exception &e, RRType type) | 341 writeExceptionJson(const exception &e, RRType type) |
285 { | 342 { |
286 Json j = VampJson::fromError(e.what(), type, Json()); | 343 Json j = VampJson::fromError(e.what(), type, Json()); |
287 cout << j.dump() << endl; | 344 cout << j.dump() << endl; |
288 } | 345 } |
289 | 346 |
370 | 427 |
371 writeMessageToFd(1, message); | 428 writeMessageToFd(1, message); |
372 } | 429 } |
373 | 430 |
374 void | 431 void |
375 writeExceptionCapnp(const std::exception &e, RRType type) | 432 writeExceptionCapnp(const exception &e, RRType type) |
376 { | 433 { |
377 capnp::MallocMessageBuilder message; | 434 capnp::MallocMessageBuilder message; |
378 piper::RpcResponse::Builder builder = message.initRoot<piper::RpcResponse>(); | 435 piper::RpcResponse::Builder builder = message.initRoot<piper::RpcResponse>(); |
379 VampnProto::buildRpcResponse_Exception(builder, e, type); | 436 VampnProto::buildRpcResponse_Exception(builder, e, type); |
380 | 437 |
504 } | 561 } |
505 | 562 |
506 void | 563 void |
507 writeResponse(string format, RequestOrResponse &rr) | 564 writeResponse(string format, RequestOrResponse &rr) |
508 { | 565 { |
566 resumeOutput(); | |
509 if (format == "capnp") { | 567 if (format == "capnp") { |
510 writeResponseCapnp(rr); | 568 writeResponseCapnp(rr); |
511 } else if (format == "json") { | 569 } else if (format == "json") { |
512 writeResponseJson(rr, false); | 570 writeResponseJson(rr, false); |
513 } else { | 571 } else { |
514 throw runtime_error("unknown output format \"" + format + "\""); | 572 throw runtime_error("unknown output format \"" + format + "\""); |
515 } | 573 } |
574 suspendOutput(); | |
516 } | 575 } |
517 | 576 |
518 void | 577 void |
519 writeException(string format, const std::exception &e, RRType type) | 578 writeException(string format, const exception &e, RRType type) |
520 { | 579 { |
580 resumeOutput(); | |
521 if (format == "capnp") { | 581 if (format == "capnp") { |
522 writeExceptionCapnp(e, type); | 582 writeExceptionCapnp(e, type); |
523 } else if (format == "json") { | 583 } else if (format == "json") { |
524 writeExceptionJson(e, type); | 584 writeExceptionJson(e, type); |
525 } else { | 585 } else { |
526 throw runtime_error("unknown output format \"" + format + "\""); | 586 throw runtime_error("unknown output format \"" + format + "\""); |
527 } | 587 } |
588 suspendOutput(); | |
528 } | 589 } |
529 | 590 |
530 int main(int argc, char **argv) | 591 int main(int argc, char **argv) |
531 { | 592 { |
532 if (argc != 2 && argc != 3) { | 593 if (argc != 2 && argc != 3) { |
561 | 622 |
562 if (format != "capnp" && format != "json") { | 623 if (format != "capnp" && format != "json") { |
563 usage(); | 624 usage(); |
564 } | 625 } |
565 | 626 |
566 #ifdef _WIN32 | 627 try { |
567 if (format == "capnp") { | 628 initFds(format == "capnp"); |
568 int result = _setmode(_fileno(stdin), _O_BINARY); | 629 } catch (exception &e) { |
569 if (result == -1) { | 630 cerr << "ERROR: " << e.what() << endl; |
570 cerr << "Failed to set binary mode on stdin, necessary for capnp format" << endl; | 631 exit(1); |
571 exit(1); | 632 } |
572 } | 633 |
573 result = _setmode(_fileno(stdout), _O_BINARY); | 634 suspendOutput(); |
574 if (result == -1) { | |
575 cerr << "Failed to set binary mode on stdout, necessary for capnp format" << endl; | |
576 exit(1); | |
577 } | |
578 } | |
579 #endif | |
580 | 635 |
581 if (debug) { | 636 if (debug) { |
582 cerr << myname << " " << pid << ": waiting for format: " << format << endl; | 637 cerr << myname << " " << pid << ": waiting for format: " << format << endl; |
583 } | 638 } |
584 | 639 |
585 while (true) { | 640 while (true) { |
586 | 641 |
587 RequestOrResponse request; | 642 RequestOrResponse request; |
588 | 643 |
589 try { | 644 try { |
625 } | 680 } |
626 mapper.removePlugin(h); | 681 mapper.removePlugin(h); |
627 delete request.finishRequest.plugin; | 682 delete request.finishRequest.plugin; |
628 } | 683 } |
629 | 684 |
630 } catch (std::exception &e) { | 685 } catch (exception &e) { |
631 | 686 |
632 if (debug) { | 687 if (debug) { |
633 cerr << myname << " " << pid << ": error: " << e.what() << endl; | 688 cerr << myname << " " << pid << ": error: " << e.what() << endl; |
634 } | 689 } |
635 | 690 |