1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gio.Subprocess; 26 27 private import gio.AsyncResultIF; 28 private import gio.Cancellable; 29 private import gio.InitableIF; 30 private import gio.InitableT; 31 private import gio.InputStream; 32 private import gio.OutputStream; 33 private import gio.c.functions; 34 public import gio.c.types; 35 private import glib.Bytes; 36 private import glib.ConstructionException; 37 private import glib.ErrorG; 38 private import glib.GException; 39 private import glib.Str; 40 private import gobject.ObjectG; 41 public import gtkc.giotypes; 42 43 44 /** 45 * #GSubprocess allows the creation of and interaction with child 46 * processes. 47 * 48 * Processes can be communicated with using standard GIO-style APIs (ie: 49 * #GInputStream, #GOutputStream). There are GIO-style APIs to wait for 50 * process termination (ie: cancellable and with an asynchronous 51 * variant). 52 * 53 * There is an API to force a process to terminate, as well as a 54 * race-free API for sending UNIX signals to a subprocess. 55 * 56 * One major advantage that GIO brings over the core GLib library is 57 * comprehensive API for asynchronous I/O, such 58 * g_output_stream_splice_async(). This makes GSubprocess 59 * significantly more powerful and flexible than equivalent APIs in 60 * some other languages such as the `subprocess.py` 61 * included with Python. For example, using #GSubprocess one could 62 * create two child processes, reading standard output from the first, 63 * processing it, and writing to the input stream of the second, all 64 * without blocking the main loop. 65 * 66 * A powerful g_subprocess_communicate() API is provided similar to the 67 * `communicate()` method of `subprocess.py`. This enables very easy 68 * interaction with a subprocess that has been opened with pipes. 69 * 70 * #GSubprocess defaults to tight control over the file descriptors open 71 * in the child process, avoiding dangling-fd issues that are caused by 72 * a simple fork()/exec(). The only open file descriptors in the 73 * spawned process are ones that were explicitly specified by the 74 * #GSubprocess API (unless %G_SUBPROCESS_FLAGS_INHERIT_FDS was 75 * specified). 76 * 77 * #GSubprocess will quickly reap all child processes as they exit, 78 * avoiding "zombie processes" remaining around for long periods of 79 * time. g_subprocess_wait() can be used to wait for this to happen, 80 * but it will happen even without the call being explicitly made. 81 * 82 * As a matter of principle, #GSubprocess has no API that accepts 83 * shell-style space-separated strings. It will, however, match the 84 * typical shell behaviour of searching the PATH for executables that do 85 * not contain a directory separator in their name. 86 * 87 * #GSubprocess attempts to have a very simple API for most uses (ie: 88 * spawning a subprocess with arguments and support for most typical 89 * kinds of input and output redirection). See g_subprocess_new(). The 90 * #GSubprocessLauncher API is provided for more complicated cases 91 * (advanced types of redirection, environment variable manipulation, 92 * change of working directory, child setup functions, etc). 93 * 94 * A typical use of #GSubprocess will involve calling 95 * g_subprocess_new(), followed by g_subprocess_wait_async() or 96 * g_subprocess_wait(). After the process exits, the status can be 97 * checked using functions such as g_subprocess_get_if_exited() (which 98 * are similar to the familiar WIFEXITED-style POSIX macros). 99 * 100 * Since: 2.40 101 */ 102 public class Subprocess : ObjectG, InitableIF 103 { 104 /** the main Gtk struct */ 105 protected GSubprocess* gSubprocess; 106 107 /** Get the main Gtk struct */ 108 public GSubprocess* getSubprocessStruct(bool transferOwnership = false) 109 { 110 if (transferOwnership) 111 ownedRef = false; 112 return gSubprocess; 113 } 114 115 /** the main Gtk struct as a void* */ 116 protected override void* getStruct() 117 { 118 return cast(void*)gSubprocess; 119 } 120 121 protected override void setStruct(GObject* obj) 122 { 123 gSubprocess = cast(GSubprocess*)obj; 124 super.setStruct(obj); 125 } 126 127 /** 128 * Sets our main struct and passes it to the parent class. 129 */ 130 public this (GSubprocess* gSubprocess, bool ownedRef = false) 131 { 132 this.gSubprocess = gSubprocess; 133 super(cast(GObject*)gSubprocess, ownedRef); 134 } 135 136 // add the Initable capabilities 137 mixin InitableT!(GSubprocess); 138 139 140 /** */ 141 public static GType getType() 142 { 143 return g_subprocess_get_type(); 144 } 145 146 /** 147 * Create a new process with the given flags and argument list. 148 * 149 * The argument list is expected to be %NULL-terminated. 150 * 151 * Params: 152 * argv = commandline arguments for the subprocess 153 * flags = flags that define the behaviour of the subprocess 154 * 155 * Returns: A newly created #GSubprocess, or %NULL on error (and @error 156 * will be set) 157 * 158 * Since: 2.40 159 * 160 * Throws: GException on failure. 161 * Throws: ConstructionException GTK+ fails to create the object. 162 */ 163 public this(string[] argv, GSubprocessFlags flags) 164 { 165 GError* err = null; 166 167 auto p = g_subprocess_newv(Str.toStringzArray(argv), flags, &err); 168 169 if (err !is null) 170 { 171 throw new GException( new ErrorG(err) ); 172 } 173 174 if(p is null) 175 { 176 throw new ConstructionException("null returned by newv"); 177 } 178 179 this(cast(GSubprocess*) p, true); 180 } 181 182 /** 183 * Communicate with the subprocess until it terminates, and all input 184 * and output has been completed. 185 * 186 * If @stdin_buf is given, the subprocess must have been created with 187 * %G_SUBPROCESS_FLAGS_STDIN_PIPE. The given data is fed to the 188 * stdin of the subprocess and the pipe is closed (ie: EOF). 189 * 190 * At the same time (as not to cause blocking when dealing with large 191 * amounts of data), if %G_SUBPROCESS_FLAGS_STDOUT_PIPE or 192 * %G_SUBPROCESS_FLAGS_STDERR_PIPE were used, reads from those 193 * streams. The data that was read is returned in @stdout and/or 194 * the @stderr. 195 * 196 * If the subprocess was created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE, 197 * @stdout_buf will contain the data read from stdout. Otherwise, for 198 * subprocesses not created with %G_SUBPROCESS_FLAGS_STDOUT_PIPE, 199 * @stdout_buf will be set to %NULL. Similar provisions apply to 200 * @stderr_buf and %G_SUBPROCESS_FLAGS_STDERR_PIPE. 201 * 202 * As usual, any output variable may be given as %NULL to ignore it. 203 * 204 * If you desire the stdout and stderr data to be interleaved, create 205 * the subprocess with %G_SUBPROCESS_FLAGS_STDOUT_PIPE and 206 * %G_SUBPROCESS_FLAGS_STDERR_MERGE. The merged result will be returned 207 * in @stdout_buf and @stderr_buf will be set to %NULL. 208 * 209 * In case of any error (including cancellation), %FALSE will be 210 * returned with @error set. Some or all of the stdin data may have 211 * been written. Any stdout or stderr data that has been read will be 212 * discarded. None of the out variables (aside from @error) will have 213 * been set to anything in particular and should not be inspected. 214 * 215 * In the case that %TRUE is returned, the subprocess has exited and the 216 * exit status inspection APIs (eg: g_subprocess_get_if_exited(), 217 * g_subprocess_get_exit_status()) may be used. 218 * 219 * You should not attempt to use any of the subprocess pipes after 220 * starting this function, since they may be left in strange states, 221 * even if the operation was cancelled. You should especially not 222 * attempt to interact with the pipes while the operation is in progress 223 * (either from another thread or if using the asynchronous version). 224 * 225 * Params: 226 * stdinBuf = data to send to the stdin of the subprocess, or %NULL 227 * cancellable = a #GCancellable 228 * stdoutBuf = data read from the subprocess stdout 229 * stderrBuf = data read from the subprocess stderr 230 * 231 * Returns: %TRUE if successful 232 * 233 * Since: 2.40 234 * 235 * Throws: GException on failure. 236 */ 237 public bool communicate(Bytes stdinBuf, Cancellable cancellable, out Bytes stdoutBuf, out Bytes stderrBuf) 238 { 239 GBytes* outstdoutBuf = null; 240 GBytes* outstderrBuf = null; 241 GError* err = null; 242 243 auto p = g_subprocess_communicate(gSubprocess, (stdinBuf is null) ? null : stdinBuf.getBytesStruct(), (cancellable is null) ? null : cancellable.getCancellableStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 244 245 if (err !is null) 246 { 247 throw new GException( new ErrorG(err) ); 248 } 249 250 stdoutBuf = new Bytes(outstdoutBuf); 251 stderrBuf = new Bytes(outstderrBuf); 252 253 return p; 254 } 255 256 /** 257 * Asynchronous version of g_subprocess_communicate(). Complete 258 * invocation with g_subprocess_communicate_finish(). 259 * 260 * Params: 261 * stdinBuf = Input data, or %NULL 262 * cancellable = Cancellable 263 * callback = Callback 264 * userData = User data 265 */ 266 public void communicateAsync(Bytes stdinBuf, Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 267 { 268 g_subprocess_communicate_async(gSubprocess, (stdinBuf is null) ? null : stdinBuf.getBytesStruct(), (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 269 } 270 271 /** 272 * Complete an invocation of g_subprocess_communicate_async(). 273 * 274 * Params: 275 * result = Result 276 * stdoutBuf = Return location for stdout data 277 * stderrBuf = Return location for stderr data 278 * 279 * Throws: GException on failure. 280 */ 281 public bool communicateFinish(AsyncResultIF result, out Bytes stdoutBuf, out Bytes stderrBuf) 282 { 283 GBytes* outstdoutBuf = null; 284 GBytes* outstderrBuf = null; 285 GError* err = null; 286 287 auto p = g_subprocess_communicate_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 288 289 if (err !is null) 290 { 291 throw new GException( new ErrorG(err) ); 292 } 293 294 stdoutBuf = new Bytes(outstdoutBuf); 295 stderrBuf = new Bytes(outstderrBuf); 296 297 return p; 298 } 299 300 /** 301 * Like g_subprocess_communicate(), but validates the output of the 302 * process as UTF-8, and returns it as a regular NUL terminated string. 303 * 304 * Params: 305 * stdinBuf = data to send to the stdin of the subprocess, or %NULL 306 * cancellable = a #GCancellable 307 * stdoutBuf = data read from the subprocess stdout 308 * stderrBuf = data read from the subprocess stderr 309 * 310 * Throws: GException on failure. 311 */ 312 public bool communicateUtf8(string stdinBuf, Cancellable cancellable, out string stdoutBuf, out string stderrBuf) 313 { 314 char* outstdoutBuf = null; 315 char* outstderrBuf = null; 316 GError* err = null; 317 318 auto p = g_subprocess_communicate_utf8(gSubprocess, Str.toStringz(stdinBuf), (cancellable is null) ? null : cancellable.getCancellableStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 319 320 if (err !is null) 321 { 322 throw new GException( new ErrorG(err) ); 323 } 324 325 stdoutBuf = Str.toString(outstdoutBuf); 326 stderrBuf = Str.toString(outstderrBuf); 327 328 return p; 329 } 330 331 /** 332 * Asynchronous version of g_subprocess_communicate_utf8(). Complete 333 * invocation with g_subprocess_communicate_utf8_finish(). 334 * 335 * Params: 336 * stdinBuf = Input data, or %NULL 337 * cancellable = Cancellable 338 * callback = Callback 339 * userData = User data 340 */ 341 public void communicateUtf8Async(string stdinBuf, Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 342 { 343 g_subprocess_communicate_utf8_async(gSubprocess, Str.toStringz(stdinBuf), (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 344 } 345 346 /** 347 * Complete an invocation of g_subprocess_communicate_utf8_async(). 348 * 349 * Params: 350 * result = Result 351 * stdoutBuf = Return location for stdout data 352 * stderrBuf = Return location for stderr data 353 * 354 * Throws: GException on failure. 355 */ 356 public bool communicateUtf8Finish(AsyncResultIF result, out string stdoutBuf, out string stderrBuf) 357 { 358 char* outstdoutBuf = null; 359 char* outstderrBuf = null; 360 GError* err = null; 361 362 auto p = g_subprocess_communicate_utf8_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &outstdoutBuf, &outstderrBuf, &err) != 0; 363 364 if (err !is null) 365 { 366 throw new GException( new ErrorG(err) ); 367 } 368 369 stdoutBuf = Str.toString(outstdoutBuf); 370 stderrBuf = Str.toString(outstderrBuf); 371 372 return p; 373 } 374 375 /** 376 * Use an operating-system specific method to attempt an immediate, 377 * forceful termination of the process. There is no mechanism to 378 * determine whether or not the request itself was successful; 379 * however, you can use g_subprocess_wait() to monitor the status of 380 * the process after calling this function. 381 * 382 * On Unix, this function sends %SIGKILL. 383 * 384 * Since: 2.40 385 */ 386 public void forceExit() 387 { 388 g_subprocess_force_exit(gSubprocess); 389 } 390 391 /** 392 * Check the exit status of the subprocess, given that it exited 393 * normally. This is the value passed to the exit() system call or the 394 * return value from main. 395 * 396 * This is equivalent to the system WEXITSTATUS macro. 397 * 398 * It is an error to call this function before g_subprocess_wait() and 399 * unless g_subprocess_get_if_exited() returned %TRUE. 400 * 401 * Returns: the exit status 402 * 403 * Since: 2.40 404 */ 405 public int getExitStatus() 406 { 407 return g_subprocess_get_exit_status(gSubprocess); 408 } 409 410 /** 411 * On UNIX, returns the process ID as a decimal string. 412 * On Windows, returns the result of GetProcessId() also as a string. 413 */ 414 public string getIdentifier() 415 { 416 return Str.toString(g_subprocess_get_identifier(gSubprocess)); 417 } 418 419 /** 420 * Check if the given subprocess exited normally (ie: by way of exit() 421 * or return from main()). 422 * 423 * This is equivalent to the system WIFEXITED macro. 424 * 425 * It is an error to call this function before g_subprocess_wait() has 426 * returned. 427 * 428 * Returns: %TRUE if the case of a normal exit 429 * 430 * Since: 2.40 431 */ 432 public bool getIfExited() 433 { 434 return g_subprocess_get_if_exited(gSubprocess) != 0; 435 } 436 437 /** 438 * Check if the given subprocess terminated in response to a signal. 439 * 440 * This is equivalent to the system WIFSIGNALED macro. 441 * 442 * It is an error to call this function before g_subprocess_wait() has 443 * returned. 444 * 445 * Returns: %TRUE if the case of termination due to a signal 446 * 447 * Since: 2.40 448 */ 449 public bool getIfSignaled() 450 { 451 return g_subprocess_get_if_signaled(gSubprocess) != 0; 452 } 453 454 /** 455 * Gets the raw status code of the process, as from waitpid(). 456 * 457 * This value has no particular meaning, but it can be used with the 458 * macros defined by the system headers such as WIFEXITED. It can also 459 * be used with g_spawn_check_exit_status(). 460 * 461 * It is more likely that you want to use g_subprocess_get_if_exited() 462 * followed by g_subprocess_get_exit_status(). 463 * 464 * It is an error to call this function before g_subprocess_wait() has 465 * returned. 466 * 467 * Returns: the (meaningless) waitpid() exit status from the kernel 468 * 469 * Since: 2.40 470 */ 471 public int getStatus() 472 { 473 return g_subprocess_get_status(gSubprocess); 474 } 475 476 /** 477 * Gets the #GInputStream from which to read the stderr output of 478 * @subprocess. 479 * 480 * The process must have been created with 481 * %G_SUBPROCESS_FLAGS_STDERR_PIPE. 482 * 483 * Returns: the stderr pipe 484 * 485 * Since: 2.40 486 */ 487 public InputStream getStderrPipe() 488 { 489 auto p = g_subprocess_get_stderr_pipe(gSubprocess); 490 491 if(p is null) 492 { 493 return null; 494 } 495 496 return ObjectG.getDObject!(InputStream)(cast(GInputStream*) p); 497 } 498 499 /** 500 * Gets the #GOutputStream that you can write to in order to give data 501 * to the stdin of @subprocess. 502 * 503 * The process must have been created with 504 * %G_SUBPROCESS_FLAGS_STDIN_PIPE. 505 * 506 * Returns: the stdout pipe 507 * 508 * Since: 2.40 509 */ 510 public OutputStream getStdinPipe() 511 { 512 auto p = g_subprocess_get_stdin_pipe(gSubprocess); 513 514 if(p is null) 515 { 516 return null; 517 } 518 519 return ObjectG.getDObject!(OutputStream)(cast(GOutputStream*) p); 520 } 521 522 /** 523 * Gets the #GInputStream from which to read the stdout output of 524 * @subprocess. 525 * 526 * The process must have been created with 527 * %G_SUBPROCESS_FLAGS_STDOUT_PIPE. 528 * 529 * Returns: the stdout pipe 530 * 531 * Since: 2.40 532 */ 533 public InputStream getStdoutPipe() 534 { 535 auto p = g_subprocess_get_stdout_pipe(gSubprocess); 536 537 if(p is null) 538 { 539 return null; 540 } 541 542 return ObjectG.getDObject!(InputStream)(cast(GInputStream*) p); 543 } 544 545 /** 546 * Checks if the process was "successful". A process is considered 547 * successful if it exited cleanly with an exit status of 0, either by 548 * way of the exit() system call or return from main(). 549 * 550 * It is an error to call this function before g_subprocess_wait() has 551 * returned. 552 * 553 * Returns: %TRUE if the process exited cleanly with a exit status of 0 554 * 555 * Since: 2.40 556 */ 557 public bool getSuccessful() 558 { 559 return g_subprocess_get_successful(gSubprocess) != 0; 560 } 561 562 /** 563 * Get the signal number that caused the subprocess to terminate, given 564 * that it terminated due to a signal. 565 * 566 * This is equivalent to the system WTERMSIG macro. 567 * 568 * It is an error to call this function before g_subprocess_wait() and 569 * unless g_subprocess_get_if_signaled() returned %TRUE. 570 * 571 * Returns: the signal causing termination 572 * 573 * Since: 2.40 574 */ 575 public int getTermSig() 576 { 577 return g_subprocess_get_term_sig(gSubprocess); 578 } 579 580 /** 581 * Sends the UNIX signal @signal_num to the subprocess, if it is still 582 * running. 583 * 584 * This API is race-free. If the subprocess has terminated, it will not 585 * be signalled. 586 * 587 * This API is not available on Windows. 588 * 589 * Params: 590 * signalNum = the signal number to send 591 * 592 * Since: 2.40 593 */ 594 public void sendSignal(int signalNum) 595 { 596 g_subprocess_send_signal(gSubprocess, signalNum); 597 } 598 599 /** 600 * Synchronously wait for the subprocess to terminate. 601 * 602 * After the process terminates you can query its exit status with 603 * functions such as g_subprocess_get_if_exited() and 604 * g_subprocess_get_exit_status(). 605 * 606 * This function does not fail in the case of the subprocess having 607 * abnormal termination. See g_subprocess_wait_check() for that. 608 * 609 * Cancelling @cancellable doesn't kill the subprocess. Call 610 * g_subprocess_force_exit() if it is desirable. 611 * 612 * Params: 613 * cancellable = a #GCancellable 614 * 615 * Returns: %TRUE on success, %FALSE if @cancellable was cancelled 616 * 617 * Since: 2.40 618 * 619 * Throws: GException on failure. 620 */ 621 public bool wait(Cancellable cancellable) 622 { 623 GError* err = null; 624 625 auto p = g_subprocess_wait(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), &err) != 0; 626 627 if (err !is null) 628 { 629 throw new GException( new ErrorG(err) ); 630 } 631 632 return p; 633 } 634 635 /** 636 * Wait for the subprocess to terminate. 637 * 638 * This is the asynchronous version of g_subprocess_wait(). 639 * 640 * Params: 641 * cancellable = a #GCancellable, or %NULL 642 * callback = a #GAsyncReadyCallback to call when the operation is complete 643 * userData = user_data for @callback 644 * 645 * Since: 2.40 646 */ 647 public void waitAsync(Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 648 { 649 g_subprocess_wait_async(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 650 } 651 652 /** 653 * Combines g_subprocess_wait() with g_spawn_check_exit_status(). 654 * 655 * Params: 656 * cancellable = a #GCancellable 657 * 658 * Returns: %TRUE on success, %FALSE if process exited abnormally, or 659 * @cancellable was cancelled 660 * 661 * Since: 2.40 662 * 663 * Throws: GException on failure. 664 */ 665 public bool waitCheck(Cancellable cancellable) 666 { 667 GError* err = null; 668 669 auto p = g_subprocess_wait_check(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), &err) != 0; 670 671 if (err !is null) 672 { 673 throw new GException( new ErrorG(err) ); 674 } 675 676 return p; 677 } 678 679 /** 680 * Combines g_subprocess_wait_async() with g_spawn_check_exit_status(). 681 * 682 * This is the asynchronous version of g_subprocess_wait_check(). 683 * 684 * Params: 685 * cancellable = a #GCancellable, or %NULL 686 * callback = a #GAsyncReadyCallback to call when the operation is complete 687 * userData = user_data for @callback 688 * 689 * Since: 2.40 690 */ 691 public void waitCheckAsync(Cancellable cancellable, GAsyncReadyCallback callback, void* userData) 692 { 693 g_subprocess_wait_check_async(gSubprocess, (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData); 694 } 695 696 /** 697 * Collects the result of a previous call to 698 * g_subprocess_wait_check_async(). 699 * 700 * Params: 701 * result = the #GAsyncResult passed to your #GAsyncReadyCallback 702 * 703 * Returns: %TRUE if successful, or %FALSE with @error set 704 * 705 * Since: 2.40 706 * 707 * Throws: GException on failure. 708 */ 709 public bool waitCheckFinish(AsyncResultIF result) 710 { 711 GError* err = null; 712 713 auto p = g_subprocess_wait_check_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &err) != 0; 714 715 if (err !is null) 716 { 717 throw new GException( new ErrorG(err) ); 718 } 719 720 return p; 721 } 722 723 /** 724 * Collects the result of a previous call to 725 * g_subprocess_wait_async(). 726 * 727 * Params: 728 * result = the #GAsyncResult passed to your #GAsyncReadyCallback 729 * 730 * Returns: %TRUE if successful, or %FALSE with @error set 731 * 732 * Since: 2.40 733 * 734 * Throws: GException on failure. 735 */ 736 public bool waitFinish(AsyncResultIF result) 737 { 738 GError* err = null; 739 740 auto p = g_subprocess_wait_finish(gSubprocess, (result is null) ? null : result.getAsyncResultStruct(), &err) != 0; 741 742 if (err !is null) 743 { 744 throw new GException( new ErrorG(err) ); 745 } 746 747 return p; 748 } 749 }