Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Martin Vieregg

Pages: [1] 2 3 ... 7
>because new processes  are _NOT_ direct children of CmdMe

How do I have to execute cmd.exe so it gets a direct children of my program?

>I would like to receive a copy of MShell

Now I have fixed some other bugs and I can show the current state of the project to others. I have changed the name now to CmdMe because MShell is already occupied (a PMShell substitute for OS/2). If anyone has got a better name for the program, please tell it here.

In the attachment, you will find the current exe (version number 0.10). I have written all important stuff into the readme text file.

If we totally fail with sending exceptions to cmd.exe, I will run cmd.exe synchronously and suspend and kill the thread. This will work, but is not the preffered solution.

>can you give me kind of test to run on my system ?

See Reply #45. Here you can download SendException.exe. It is compiled with WDsibyl (Pascal). Meanwhile, I have compiled the EDM sample code with a C compiler, same result. The behaviour is the same like in my main program.

If SendSignalException and its relatives does not work at all, what is the purpose of these functions? Is it a bug? Does anyone has a Warp 3 (or 2.1) installation running?

We could send the exception to a different program to see if the problem is located in cmd.exe. I am not very familar with Exceptions. What does the Ctrl-C exception do in the target program? Is it like a keyboard input of Ctrl-C ? E.g. In ME Editor Ctrl-C is Page Down with Wordstar keyboard layout (Options - Settings - General). I haven't programmed receiving exceptions from outside yet.

>In NEPMD, it's possible to kill (and restart) the process that started CMD.EXE and it stops immediately, also visible by the CPU load.

Yes, killing and restarting will be possible (it will feel quite similar). This will be only a substitute hack if the behaviour I hope for is definitely not possible.

Another possibility is to run the child synchronous and sending the signal to the parent program PID. I tried it, but now DosSendSignalException returns 1.

>DosSendSignalException will return 205 if it receives PID other than PID of child process.
But I send the signal to the child process (81 in this case).

GO.EXE output is intersting in this case:

Code: [Select]
GO! v1.2 (Rev. 93/11/27)
(c) 1993 by Carsten Wimmer

             Parent           Num. of
Process ID Process ID Session Threads Priority Name
 Dec  Hex   Dec  Hex  Dec Hex
---------- ---------- ------- ------- -------- ---->
  51   33     0    0   21  15     1     0200   CUPSD.EXE
  46   2e     0    0   20  14     1     0200   SOCKTIDY.EXE
  32   20     1    1    1   1    30     0200     PMSHELL.EXE
  80   50    32   20   24  18     4     0200       MSHELL.EXE
  81   51    80   50   24  18     1     0200         CMD.EXE

MShell is my parent program (I will change the name later). It executes its child CMD.EXE. Nevertheless, error 205 is returned.

Silvan, a good idea. I compiled the simple text program SendException.exe.

Executing without parameter shows an help text:
sendexception.exe sends an exception to a PID. Enter the PID value in decimal first and the Execption type as second parameter.
Sample:  sendexception 197 2

To recognize the cmd.exe session to observate, run go.exe in the cmd session you want to identify: GO 1.5
The PID we need is in the first row in the line of CMD.EXE, where GO.EXE is shown as child.

In this window, I run "dir /s" which takes a lot of time.
I tried the following input and I got:

Code: [Select]
[C:\]sendexception 106 1
DosSendSignalException returns 205

[C:\]sendexception 106 2
DosSendSignalException returns 209

[C:\]sendexception 106 4
DosSendSignalException returns 205

So the behaviour corresponds to my main program. Now the question is how to send these exceptions to cmd.exe. 209 means ERROR_INVALID_SIGNAL_NUMBER  what is completely suspect to me. 205 means ERROR_NO_SIGNAL_SENT, see the link Silvan posted above.

>CTRL-C works here in Larson Manager.

When pressing Ctrl-C in Larsen Commander, I get a menu with four options:
- Ctrl-C Break
- Ctrl-Break
- exit
- kill.

Ctrl-C Break and Ctrl-Break does not work, exit and kill works. My version is 1.6 milestone 3. I run C:\>  dir /s

>So why did it work for me ? I could start a session and redirect stdout and stdin without a problem.

All works fine, but only sending the Ctrl-C exception to the cmd.exe child does not work. This is the only problem.

>Perhaps your problem is that you are sending the CTRL-C to cmd.exe instead of the child process that cmd is running, make in my example?

Yes, meanwhile I have thought about this problem, too. My main program (the editor) creates a thread where cmd.exe gets executed asynchronously, that means the thread calls  DosExecPgm call and this call returns the PID which I need for sending the exception if a user in the editor presses Ctrl-C. Then the thread waits for terminating cmd.exe by using DosWaitChild. I have only one child PID. The thread which calls DosExecPgm and then waits has only a Thread ID (TID), not a PID.

So the main interest should be at the commandline window itself. The window is a PM program and inside, there is a textmode program running. Perhaps I send the exception to the wrong part ? But I have got only one PID. (Perhaps someone can explain it further what cmd.exe is.)

>Larson Commander seems to be able to do it.

A very interesting hint. I nearly daily use Larsen Commander. The cmd output window is indeed really interesting. It even supports marking text. I haven't checked it yet under this aspect. In opposite to my program, every command starts a new instance of cmd.exe. cmd.exe and its own PID is seen in GO and TOP. That means that it also starts DosExecPgm.
But - what a pity - Ctrl-C Breaks and Ctrl-Break also does not work ! Killing and exiting works. Killing ist clear, but what is exiting (while a long output is running) ? What could be the difference to killing ?This would be an option for Ctrl-C if the classic break does not work.

Anyway, searching a program which has done the job is a goodl way to find the solution.

Laurence also assumed that it should work, but it does not.

- I start cmd.exe via DosExecPgm without failure
- I get a valid PID which corresponds to the shown value in the TOP program
- The thread where I call DosExecPgm waits correctly with DosWaitChild
- In the main thread (user input), I call DosSendSignalException with the valid PID and XCPT_SIGNAL_INTR or XCPT_SIGNAL_BREAK
- but DosSendSignalException returns error 205 and the Exception does not reach cmd.exe.

I observe the steps with a log file.

This is the problem what is discussed the last 15 posts and noone has an idea what the problem could be. A lot of reasons for malfunction are eliminated now.

Besides this point, it seems that I have got all other problems solved and the program already works fine.

I think I cannot run cmd.exe via session by using DosStartSession because only DosExecPgm inherits the standard pipes stdin/stdout/stderr. Meanwhile, I fear we're spinning circles. At the first try, I used DosStartSession and Named Pipes. And I changed to DosExecPgm and unnamed pipes with DosDupHandle with the hope of managing the Ctrl-C Interrupt communication problem. Besides this point, the two ways are basically working. But I have a weak idea that DosExecPgm is the smarter option. In both cases, I can stop it. The DosStartSession variant has got DosStopSession, the DosExecPgm variant DosKillProcess. I cannot believe that there is no solution for sending Ctrl-C to cmd.exe. If noone has got an idea to send Ctrl-C to cmd.exe, I will program a kill option in several steps: One waiting for a finished line output and the harder one with immidiately killing the process. But Ctrl-S should suspend cmd.exe. I can suspend a thread but can I suspend a process? I fear not. And what about sessions? Can I suspend sessions? How does the parent process gets informed if the session ends itseif? I also fear that it is not possible. (With the DosExecPgm variant, I can wait for finishing with DosWaitChild.) Anyway, freezing the output of the parent editor should go. But what happens if the pipe is full? Does the OS suspend the process or do I get an error?

>A process calls DosSetSignalExceptionFocus to become the signal focus.

But I cannot execte CMD.EXE code. I tried to use DosSetSignalExceptionFocus before calling DosExecPgm, but it seems that this property of the parent process is not inherited. DosSetSignalExceptionFocus always refers to the calling process and I cannot hand over a PID in the function call.

Oops, that was my failure. The return value has been set to another value later. Now the PID which I save corresponds to the TOP value. But DosSendSignalException still returns 205. My program log sends:

2020.1.14 21:40:55.699: exec DosExecPgm
2020.1.14 21:40:55.699: cmd.exe has been started. child_PID 213
2020.1.14 21:40:59.900: ScanEvent Ctrl-C, PID 213
2020.1.14 21:40:59.900: DosSendSignalException returns 205
2020.1.14 21:41:0.369: ScanEvent Ctrl-C, PID 213
2020.1.14 21:41:0.369: DosSendSignalException returns 205
2020.1.14 21:41:1.900: ExternProgThread still running
(User ends program)
2020.1.14 21:41:1.900: Bytes read 0
2020.1.14 21:41:1.900: not finished
2020.1.14 21:41:1.900: End cmd.exe child_PID 213 rc 0
2020.1.14 21:41:2.29: Bytes read 0 (from cmd.exe stdout)
2020.1.14 21:41:2.29: ExternProgThread has ended normally
2020.1.14 21:41:2.29: PipeinFinish
2020.1.14 21:41:2.29: App.Terminate

DosWaitChild works fine, the thread suspends correctly. The exception is sent via:
                  ULONG Exception = XCPT_SIGNAL_INTR;
                  rc = DosSendSignalException(child_PID, Exception);

OK, now the child (cmd.exe) runs asynchrously and I exeute DosWaitChild after starting cmd.exe by using DosExecPgm. All functions return no error. The returned PID is zero (is that normal?) The program still runs fine with the modifications.

Because my parent program is an editor which already has a function for pressing Ctrl-C, I don't think I need to install an exception handler in the main process. If the exception handler is necessary nevertheless, what do I write into the @function which is related to the exception?

Although I have now the PID, DosSendSignalException (PID, XCPT_SIGNAL_INTR) has no effect. The function is definitely executed in the main thread when pressing Ctrl-C in the parent editor. It still returns the value 205 (no process or no process with exception handler). Any ideas?

After I managed the pipes, the Ctrl-C break is still not working. At the moment, I generate a thread where cmd.exe gets executed synchronous. While running cmd.exe, the thread "hangs" in the DosExecPgm function call. The necessary DosSendSignalException call when a user in the parent program editor enters Ctrl-C needs a process identification (PID). But I have only a thread identification (TID) from my thread. How do I get the PID ? Do I have to run cmd.exe asynchronous?

Thank you for the hints, Laurence. I finished now programming (the length of the code is less now), it seems to be quite simple. After a second try, it works yet.

The main progress I made by studying a sample code popen.c

A pipe has got two ends: one for reading and one for writing. (Laurence told us that the reverse direction is also possitble.) So what to do is

1. DosCreatePipe with two handles:  A "write-end" and a "read-end" for the pipe. So a pipe is always defined by a pair of file handles. The "write-end" is for the parent program and the "read-end" for the child program when sending data from parent to child (the user enters command input in my parent editor) or reverse for sending cmd.exe output into the editor. I need three pipes for handling stdin, stdout and stderr.

2. To tell the child the correct filehandles for the child-end of the pipe, I need to use DosDupHandle. The child-end file handles are duped to the filehandle values 0, 1 2 for stdin, stdout and stderr. When using DosExecPgm to start the child program, these handles get available for the child.

Restoring and Saving the file handles with additional DosDupHandle calls are not necessary in a PM app, but can be done.

If I understand it right,

- I have to use DosCreatePipe (an unnamed pipe) three times for stdin, stdout and stderr (but at this moment, they are not assigned yet) and I will get real file handles, 3 are used, 3 are not used. Or do I only use one Pipe with read and write? (But where is stderr then?)

- I call DosDupHandle and assign them to stdin, stdout and stderr.

>you dup the read file handle to your parent process stdout
but that means reverse.

When terminating the program, what do I have to do ?

Pages: [1] 2 3 ... 7