Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Issue with pseudo terminal suspending main Linux application

This thread is locked; no one can reply to it. rss feed Print
Issue with pseudo terminal suspending main Linux application
ZoriaRPG
Member #16,714
July 2017
avatar

I have a situation here, where I tried to create a child of a process in Linux where I open an output pseudo-terminal window to show debugging output/traces, and other data, similar to a W32 API console, however, as soon as this starts, the main programme, in this case using Ag4.4.4, immediately suspends.

This is under Debian 32b, if that matters.

Why is this suspending the parent process, and how do I prevent that?

I tried to use the flag O_NOCTTY, too.

#SelectExpand
1 2 3 4#else //Unix 5 6//these are inside another earlier ifdef, but for the sake of simplicity, I am placing them here in this post: 7 8 #include <fcntl.h> 9 #include <unistd.h> 10 #include <iostream> 11 #include <sstream> 12 int pt = 0; 13 char* ptname = NULL; 14 std::ostringstream lxconsole_oss; 15 16//code for the console itself is here: 17 18 { // Let's try making a console for Linux -Z 19 pt = posix_openpt(O_RDWR); 20 if (pt == -1) 21 { 22 Z_error("Could not open pseudo terminal; error number: %d.\n", errno); 23 use_debug_console = 0; goto no_lx_console; 24 } 25 ptname = ptsname(pt); 26 if (!ptname) 27 { 28 Z_error("Could not get pseudo terminal device name.\n"); 29 close(pt); 30 use_debug_console = 0; goto no_lx_console; 31 } 32 33 if (unlockpt(pt) == -1) 34 { 35 Z_error("Could not get pseudo terminal device name.\n"); 36 close(pt); 37 use_debug_console = 0; goto no_lx_console; 38 } 39 40 lxconsole_oss << "xterm -S" << (strrchr(ptname, '/')+1) << "/" << pt << " &"; 41 system(lxconsole_oss.str().c_str()); 42 43 int xterm_fd = open(ptname,O_RDWR); 44 { 45 char c = 0; int tries = 10000; 46 do 47 { 48 read(xterm_fd, &c, 1); 49 --tries; 50 } while (c!='\n' && tries > 0); 51 } 52 53 if (dup2(pt, 1) <0) 54 { 55 Z_error("Could not redirect standard output.\n"); 56 close(pt); 57 use_debug_console = 0; goto no_lx_console; 58 } 59 if (dup2(pt, 2) <0) 60 { 61 Z_error("Could not redirect standard error output.\n"); 62 close(pt); 63 use_debug_console = 0; goto no_lx_console; 64 } 65 } //this is in a block because I want it in a block. -Z 66 67 no_lx_console: 68 { 69 //Z_error("Could not open Linux console.\n"); 70 } 71 72 73 std::cout << "\n _____ ____ __ \n"; 74 std::cout << " /__ / / __ \__ _____ _____/ /_\n"; 75 std::cout << " / / / / / / / / / _ \/ ___/ __/\n"; 76 std::cout << " / /__/ /_/ / /_/ / __(__ ) /_ \n"; 77 std::cout << " /____/\___\_\__,_/\___/____/\__/\n\n"; 78 79 std::cout << "Quest Data Logging & ZScript Debug Console\n"; 80 std::cout << "ZConsole for Linux\n\n"; 81 82 if ( FFCore.getQuestHeaderInfo(vZelda) > 0 ) 83 { 84 printf("Quest Made in ZC Version %x, Build %d\n", FFCore.getQuestHeaderInfo(vZelda), FFCore.getQuestHeaderInfo(vBuild)); 85 } 86 else 87 { 88 printf("%s, Version %s\n", ZC_PLAYER_NAME, ZC_PLAYER_V); 89 } 90 //std::cerr << "Test cerr\n\n"; 91 std::cin.ignore(1); 92#endif

bamccaig
Member #7,536
July 2006
avatar

Peter Hull
Member #1,136
March 2001

This does the thing you want, though I have a feeling there ought to be a better way. You should able to adapt it to your needs.

#SelectExpand
1#include <stdio.h> 2#include <unistd.h> 3#include <string.h> 4#include <stdlib.h> 5 6int main(void) { 7 printf("Starting\n"); 8 int fd[2]; 9 pipe(fd); 10 if (fork() == 0) { 11 /* child, close the write side */ 12 close(fd[1]); 13 char ss[128]; 14 sprintf(ss, "cat /dev/fd/%d", fd[0]); 15 execlp("xterm", "xterm", "-e", ss, NULL); 16 exit(0); 17 } else { 18 /* parent, close the read side */ 19 close(fd[0]); 20 char ss[128]; 21 int i; 22 for (i=0; i<100; ++i) { 23 sprintf(ss, "Line %d\n", i); 24 write(fd[1], ss, strlen(ss)); 25 sleep(1); 26 } 27 printf("Finishing\n"); 28 } 29 return 0; 30}

It spawns an xterm as a separate process and writes 100 lines to it. Tested on Mac, hopefully it'll be OK on linux.

ZoriaRPG
Member #16,714
July 2017
avatar

I fixed it. Of all the dumb things, it was the call to std::cin.ignore, which was no longer doing something useful, and instead was harmful, due to an earlier change.

The main point of this is to direct all printf() to their own window. I did at one point try to colourise it, but on Linux, based on the terminal software in use, there isn't a set standard for colour text output, so I pulled that out as it created illegal chars where it wasn't supported.

Anyway, the point wasn't to spit out lines in a new process, the point is to redirect all output of a process to its own window. The initial cout are just the banner of the window, but from that point on, all of the internally wrapped print commands get piped there.

The lifespan of the pseudoterminal is the lifespan of the application, and each instance of the application can have its own PT.

Note that I only rite the Linux code and patches, we have someone else trying to build this stuff, and I'm trying to teach him to use gdb right now. I need another system to run Debian as this one is in use fulltime and lacks the resources to run a VM.

Why Debian? Three reasons:

Ubuntu is now only 64b, and it is a gigantic pain to set it up to build 32b.
Versions of Ubuntu that easily support this, do not have the right deps for alegro.
Versions with the right deps for allegro do not have a compatible glibc and gcc.

I had already perma-bricked a dep tree/apt by trying to force the right glibc and gcc chain into an Ubuntu version that didn't support properly building, and I never want to need to live through that again.

Debian has everything needed, it seems. Once we have a process known to work and binaries known to work, I want to look into AppImage.

Go to: