Feedback Search Top Backward Forward
EDM/2

Questions and Answers

Written by Larry Salomon, Jr.

 

Introduction

Welcome to this month's "Scratch Patch"! Each month, I collect various items that fit into this column sent to me via email. The ones that I feel contribute the most to developers, whether in terms of information or as a nifty trick to tuck into your cap, get published in this column.

To submit an item, send it via email to my address - os2man@panix.com - and be sure to grant permission to publish it (those that forget will not be considered for publication).

Gotcha Notes!

Last week I was developing a multithreaded application that needed two-way communication between the main and secondary threads. The easiest solution, as you may well know, was to use an object window in the second thread with its own message loop. The purpose of the second thread was to perform some lengthy processing, but needed to be interruptable, i.e. if the user pressed the Abort button, the dialog would send the object window the appropriate message. After the thread terminated its processing, it would send a response back.

A problem was created, though, that resulted in deadlock. Although it didn't take long to deduce because the code was still quite skeletal (making the process of elimination quite easy), I still do not know why the deadlock occurred. In any case, it is necessary to relate the situation to the readers so that they may avoid it in their own applications.

The code looked something like the following:

objectWndProc(...)
{
   POBJECTINSTDATA poidData;

     :
   case MYM_ABORT:
      :   /* Abort processing */
      WinSendMsg(poidData->hwndDlg,MYM_PROCESSINGABORTED,0,0);
      break;
     :
}

processDlgProc(...)
{
   POBJECTINSTDATA poidData;

     :
   case WM_COMMAND:
      switch (SHORT1FROMMP(mpParm1)) {
      case DLG_PB_ABORT:
         WinPostMsg(poidData->hwndObj,MYM_ABORT,0,0);
      default:
         return WinDefDlgProc(hwndWnd,ulMsg,mpParm1,mpParm2);
      } /* endswitch */
   case MYM_PROCESSINGABORTED:
      WinDismissDlg(hwndWnd,DID_CANCEL);
      break;
     :
}

INT main(VOID)
{
   SHORT sRc;

     :
   sRc=WinDlgBox(HWND_DESKTOP,
                 HWND_DESKTOP,
                 processDlgProc,
                 NULLHANDLE,
                 DLG_PROCESS,
                 NULL);
   if (sRc!=DID_CANCEL) {
        :
   } /* endif */
     :
}
A lot was removed for clarity, but the pertinent parts are shown above. What would happen was that, while testing the communication mechanisms, whenever I would press the Abort button, the dialog would go away, but the application would not terminate; looking at the above, you can probably figure out what the problem was. The problem, in case you can't figure it out, is the WinSendMsg(...,MYM_PROCESSINGABORTED,...) call to the dialog. For some reason, if a message is sent intraprocess from the object window to the dialog and the dialog dismisses itself, the process will deadlock. Changing the WinSendMsg() to WinPostMsg() eliminated the problem.

I suspect the answer to why lies in the existence of a message loop in the object window thread, but I cannot be sure. If anyone can give a definitive answer, I would be happy to publish it.


David Charlap (david@porsche.visix.com) sent us the following:

You can include this snippet. SWEEP.CMD is a REXX program that allows you to apply any command-line to a recursive set of directories.

Syntax is:

  SWEEP <command-line>
The program will visit every subdirectory of the current directory (and all descendants thereof) and execute your command line in each one. For example, to delete every backup file on your drive, just "cd" to the root directory of the drive and type
  SWEEP DEL *.BAK
If the command you want to execute is a CMD file, be sure to use the "CALL" command, or Rexx will complain:
  SWEEP CALL MyCmdFile.CMD myArgs...