This is the mail archive of the cygwin mailing list for the Cygwin project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: rvxt-20050409-1 console problem [SUMMARY]

Charles Wilson wrote:
(2) add the "smart" hide console code to rxvt-unicode-X and remove the brute-force hide console code. Otherwise, the Igors of the world will have the same "where'd my console go" problem with rxvt-unicode-X.

There is a downside to this. As Brian mentioned "run" is not going away -- because without it (e.g. if rxvt[-unicode-X] hides its own console after-the-fact) you will always get the briefly flashing cmd console.

Not a big deal, but annoying. But, rxvt-unicode-X can't be used with run if --login (100% CPU suckage). I dug into this, and discovered a few things:

rxvt-unicode-X has a main event loop that is completely rewritten from the one in rxvt. So it's not surprising that it behaves somewhat differently. What's going on in the problematic case (100% CPU usage if run+urxvt-X+loginShell=true) is that a select() call is always returning immediately with "data waiting" -- except that there's not REALLY any data waiting.

Because run.exe lauches the child process with no console -- not even a hidden one, actually -- the stdin/stdout/stderr handles are not initialized. [1] Somewhere -- and I haven't figured out where, yet, because the obvious place is NOT it -- rxvt-unicode-X is reopening stdin to /dev/null (well, technically, it's opening file descriptor 0 to the file /dev/ might not be "thinking" of it in terms of "stdin", per se. dup2() will automatically use the lowest available file descriptor -- and if 0 [stdin] is available, suddenly you've got stdin open again.)

Anyway, /dev/null is of course always "ready" but never actually has any data. So the event loop never 'hangs out' in the select. Instead, it's acting like a polling spinlock -- and that's bad.

So, I get the following repeated over and over -- sucking 100% CPU (and note the second line!).

31 447 [main] rxvt 2744 cygwin_select: 7, 0x22EDC0, 0x22EDB8, 0x0, 0x0
52 499 [main] rxvt 2744 dtable::select_read: /dev/null fd 0
49 548 [main] rxvt 2744 dtable::select_read: fd 4
45 593 [main] rxvt 2744 dtable::select_read: /dev/ptmx fd 6
27 620 [main] rxvt 2744 cygwin_select: to NULL, ms FFFFFFFF
92 712 [main] rxvt 2744 cygwin_select: sel.always_ready 1
24 736 [main] rxvt 2744 select_stuff::cleanup: calling cleanup routines
20 756 [main] rxvt 2744 socket_cleanup: si 0x0 si->thread 0x0
18 774 [main] rxvt 2744 socket_cleanup: returning
36 810 [main] rxvt 2744 peek_socket: considering handle 0x6D4
23 833 [main] rxvt 2744 peek_socket: adding read fd_set , fd 4
34 867 [main] rxvt 2744 peek_socket: WINSOCK_SELECT returned 0
20 887 [main] rxvt 2744 set_bits: me 0x702AC0, testing fd 0 (/dev/null)
19 906 [main] rxvt 2744 set_bits: ready 1
18 924 [main] rxvt 2744 select_stuff::poll: returning 1
18 942 [main] rxvt 2744 select_stuff::cleanup: calling cleanup routines
19 961 [main] rxvt 2744 select_stuff::~select_stuff: deleting select records
67 1028 [main] rxvt 2744 set_signal_mask: oldmask 0x0, newmask 0x84002, mask_bits 0x0
19 1047 [main] rxvt 2744 set_signal_mask: not calling sig_dispatch_pending
21 1068 [main] rxvt 2744 readv: readv (0, 0x22ED50, 1) blocking, sigcatchers 3
21 1089 [main] rxvt 2744 readv: no need to call ready_for_read
20 1109 [main] rxvt 2744 fhandler_base::read: returning 0, binary mode
18 1127 [main] rxvt 2744 readv: 0 = readv (0, 0x22ED50, 1), errno 0
21 1148 [main] rxvt 2744 set_signal_mask: oldmask 0x84002, newmask 0x0, mask_bits 0x84002
20 1168 [main] rxvt 2744 cygwin_select: 7, 0x22EDC0, 0x22EDB8, 0x0, 0x0

[1] Here's the important bit from run.exe:

   memset (&start, 0, sizeof (start));
   start.cb = sizeof (start);
   start.wShowWindow = SW_HIDE;
   start.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
   start.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
   start.hStdError = GetStdHandle(STD_ERROR_HANDLE);

   sec_attrs.nLength = sizeof (sec_attrs);
   sec_attrs.lpSecurityDescriptor = NULL;
   sec_attrs.bInheritHandle = FALSE;

   if (CreateProcess (NULL, cmdline, &sec_attrs, NULL, TRUE, 0,
                      NULL, NULL, &start, &child))

Sure, it's *supposedly* setting start.hStdInput and friends to The Right Thing, but according to MSDN (in the AllocConsole() description):

"GUI applications are initialized without a console. Console applications are initialized with a console, unless they are created as detached processes (by calling the CreateProcess function with the DETACHED_PROCESS flag)."

Since run.exe is a GUI app, it has no console at all -- and therefore GetStdHandle() returns INVALID_HANDLE_VALUE, which isn't a very nice thing to initialize start.hStdInput and friends to.

But here's the thing: run.exe's job is to launch an application without a *visible* console. **NOT** necessarily to launch the application with no console whatsoever, and with closed stdio handles. It's "run.exe", not "daemonize.exe" -- and some applications, even GUI apps, don't react well when treated like daemons.

But run.exe can't simply call AllocConsole() -- there's no [easy] way to say "AllocConsole(but make it hidden)". You'd have to AllocConsole and then use the hide_console routines -- and now you're back to flashing windows again.


What to do?

First, I believe there are two problems:

(1) rxvt-unicode-X really should handle having stdin closed (or set to /dev/null) more gracefully. Why is stdin even being listened to in the event loop, anyway? Or is this a dup2() problem, where the closed fd 0 is being reused? Dunno. Needs more looking at.

(2) run.exe should try at least as hard as cygwin1.dll to provide for the expectations of its clients: if possible, give them a hidden console with working stdio. Again, it's "run.exe", not "daemonize.exe".

Well, I've got a patch for run.exe that borrows code from cygwin's fhandler_init routines, to enable run.exe, a GUI app, to AllocConsole() but NOT flash. To do this, it uses some routines in user32.dll that are only available on WinNT/2k/XP -- so I did the whole LoadLibrary/GetProcAddress dance with function pointers; end result should be no change from current behavior for w95/98/Me. It would be nice if there was some other code that could be used to similar purpose on those older OSes -- maybe I need to 'borrow' from some other area of cygwin...unfortunately, I have no w95/98/Me machine to test on, so I'm hesistant to code blindly.

Anyway, with this change on WinXP(and presumably 2k/NT), rxvt-unicode-X + new-run.exe + loginShell = true works just fine, no 100% CPU suckage. I'll post that patch in a new thread.

The second problem -- rxvt-unicode-X ought to behave better when it has no stdin -- is a little more difficult. I need to verify that it behaves just as badly on linux when launched via a daemonizer. If so, then it's time for heavy duty debugging -- and maybe a report back to the upstream developers. If not...err, uhm, well...I've been wrong before...

(3) (b) forget about scripts. Use a special version of "run" specifically for the purpose of switching between rxvt versions. For user customizability, maybe it could read configuration info
from a file in /etc. This rxvt-launcher would be a -mwindows app, just like run. It would use the checkX program (or borrow the code; sigh. Time for a library?) to determine Xness, and launch the apropriate client using !SW_VISIBLE, just like run. But it wouldn't have any of run's introspection code ("what was my own argv[0]? Did it match 'run?????.exe' where ????? non-empty? Search PATH for ?????.) nor would it need to have any PATH walking code at all -- require that configuration info contain full PATH. (It would need to resolve symlinks, tho).

I'm leaning toward this solution, in a more generic sense, like: "gui-switcher.exe --config=/etc/rxvt-selector.conf"

It'll go into the checkX package since it'll leverage a lot of the same code. And that's why I need to track down these issues with rxvt-unicode-X+run+loginShell...'cause if they are not solved with run.exe, they'll show up again with gui-switcher.exe.


Unsubscribe info:
Problem reports:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]