Hi Jack,
?2009?12?19??04:41?Jack Schwartz???
> Hi Zhongyuan.
>
> On 12/17/09 22:20, zhongyuan sun - Sun Microsystems - Beijing China
> wrote:
> > Looks good! a little clarification,
> >
> > ?2009?12?18??08:17?Jack Schwartz???
> >
> > > Hi Zhongyuan.
> > >
> > > Thanks for your feedback.
> > >
> > > On 12/16/09 22:45, zhongyuan sun - Sun Microsystems - Beijing China
> > > wrote:
> > >
> > > > Hi Jack,
> > > >
> > > > Thanks your quick response. my comments:
> > > >
> > > > (1)I'm not very clear about class devscan_data, what its main function?
> > > > so far I think it's no more different with a list type. The main
> > > > scanning function was implemented by ddu_devscan(). If devscan_data only
> > > > provide like append function, I suggest just use a list but not this
> > > > additional class.
> > > >
> > > >
> > > The devscan_data class bundles the data with search functionality. (I
> > > assume this search functionality is something you need, since you had
> > > originally suggested using a dictionary.)
> > > get_list_by_devtype(devtype) is the search method.
> > > A list by itself could be used, but then you would need to add
> > > external search methods to filter the data, (like all devices of type
> > > "Audio"). It is convenient to put those methods into the same class
> > > as the data.
> > >
> > ddu_devscan function will be used in GUI/AI/Text-mode parts.
> > While in GUI part, ddu_devscan will be called separately for each
> > components(audio,network,storage....), the source code would be
> > like:ddu_devcan(return_missing_only=All, device_type="audio") and then
> > ddu_devcan(return_missing_only=All, device_type="network") and on. In
> > this way, ddu_devscan will do the search method, its return value(will
> > be stored in class devscan_data) do not need to search again.
> > For AI/Text-mode parts, ddu_devscan will be called only once and return
> > all missing driver components. But since AI/Text-mode do not care about
> > which type(audio,network...) the devices belongs to, so in this way even
> > class devscan_data provide get_list_by_devtype method, it will never be
> > called.
> > In a summary, I do not know when this method get_list_by_devtype in
> > class devscan_data will be called.
> >
> Thanks for your clarification. So get_list_by_devtype() is not
> needed, and we can just use a list at the top level.
>
> ddu_devscan() will now return a list of dev_data objects.
It's OK, Thanks.
> >
> > > Why my class instead of a dictionary? Because it is simpler and more
> > > flexible than a dictionary. This class is flexible as you can add
> > > additional search methods in the future if needed.) If a dictionary
> > > is used instead then this additional flexibility becomes harder to
> > > implement. I would think (but haven't verified this) that
> > > dictionaries are more heavyweight than the dev_data class.
> > >
> > > > (2)Which class will in charge of store "Device compatible name" string
> > > > used by ddu_package_lookup()? I did not put it in class dev_data because
> > > > I think this class only store general device information, while "Device
> > > > compatible name" is not a general information especially for that device
> > > > which already has a working driver. "Device compatible name" will be
> > > > only useful for fetching driver information. Shall we add a new function
> > > > to generate "Device compatible name"? This function's argument can be
> > > > pci path and output is "Device compatible name".
> > > >
> > > >
> > > From what I see, dev_data stores data specific to a device. (For
> > > example, attach_status and instance_ID are very specific to a
> > > device.) The compatible name string is another piece of device
> > > specific data, and so I think we should include it in dev_data.
> > > (Note: it is currently missing from dev_data; that is an oversight
> > > and will be corrected.)
> > >
> > >
> > Yes, compatible name string could be a property of class dev_data. While
> > from the implementation point of view, all the current dev_data 11
> > properties(description,driver_name,instance_ID...) are get from one
> > session(they are output from a DDU tool). We do not include compatible
> > name string as a default output because its only useful for missing
> > driver components. For that non-missing driver component DDU does not
> > use it. So for most devices the compatible name string is not a very
> > critical property for DDU, DDU only fetch it when needed that is a
> > missing driver device want to look for its driver.
> > Of course DDU can get compatible name string very easy, but it need some
> > more codes in another block. That why i suggest to create another method
> > in dev_data.
> > Again the dev_data 11
> > properties(description,driver_name,instance_ID...)are get from one
> > session and compatible name string will be fetched from another session
> > even if the method is very easy.
> > If compatible name string is a property of class dev_data, From
> > performance point of view, the non-missing driver device will set it to
> > None and missing driver device will set to its real value?
> >
> A specification assumes (and therefore limits) the use of a field when
> it specifies that field is to be set only under certain conditions.
> This is not always a bad thing, but a more versatile solution is to
> always set the field if it is going to be present. So I suggest to
> either always set the compatible name or else to not include it in the
> structure.
>
> Let's take the suggestion you made yesterday, and have a separate
> function to return the compatible name string, when given a dev_data
> object argument. This way, the DDU can get the compatible name when
> it needs it (and so performance around this will be optimized), and
> dev_data fields will be consistent.
Or you can put this function as a method of dev_data, while either
solution is OK, thanks.
>
> How about this:
>
> def get_compatible_name(dev_data):
> # Returns compatible name string
>
> > > If the compatible name string is in dev_data, do you still need the
> > > vendor_id, device_id and class_code? (I think you do, as you can use
> > > these items to locate a specific kind of device if necessary, but
> > > please confirm.)
> > >
> > Yes
> >
> OK.
> >
> > > You can already retrieve a device's compatible name string from the
> > > kernel via prtconf (and probably other ways too). Since the device
> > > compatible name string is already generated elsewhere, let's not
> > > create another function to generate it again. Duplication of existing
> > > functionality makes the code more difficult to maintain.
> > >
> > > > (3)function ddu_devscan() and ddu_package_lookup() will take a little
> > > > long time when it running, also during this time these two functions
> > > > will fork some child processes. Should we provide a mechanism to stop
> > > > these functions during it running then they can kill all their child
> > > > processes? This situation usually happens in GUI environment.
> > > >
> > > >
> > > I think providing a way for the parent to kill its child processes is
> > > a good idea. However, I would try to make it automatic via a signal
> > > handler. When the parent receives a signal to die, have it catch that
> > > catch and process its signal by signaling each of its children to die
> > > gracefully before terminating itself.
> > >
> > This is exactly what i want, all the child process will be killed via
> > signal. I just want a way for these two functions ddu_devscan() and
> > ddu_package_lookup() can send kill signals to their child processes. For
> > example, can we set a argument for these functions? If the function
> > found this argument has been set to True, then they can have a chance to
> > send kill signals to child processes.
> >
> I think what you are suggesting is that ddu_devscan and
> ddu_package_lookup will spawn subprocesses when called with an
> argument "termination=False" and to kill the subprocesses they spawned
> when called with "termination=True". Do I understand correctly?
>
> Assuming I understand correctly, I don't think the additional arg is
> necessary. Just have their parent (whoever calls ddu_devcscan and
> ddu_package_lookup) send a signal to the process group at termination
> time. This will terminate those subprocesses plus all of their
> children. If you don't want to terminate the parent at that time, set
> it up to ignore the signal before sending it.
>
Thanks, this way make things simple.
> I wrote and attached a sample shell and python program to show how
> this can be done. You may need to do a hybrid approach of the two
> programs depending on how your library is set up.
>
> Since we seem to be converging, I'm going to update the spec again.
> If you have more issues or if I didn't understand you correctly,
> please reply ASAP.
>
> Thanks,
> Jack
>
> P.S. Don't use these sample programs as examples of final form.
> Though they are reasonably clean, I haven't checked them for PEP8
> compliance or style conformity, etc.
> > Thanks,
> > Zhongyuan
> >
> > > Thanks,
> > > Jack
> > >
> > > > Also thanks Keith's review, I agree with his comments.
> > > >
> > > > Thank,
> > > > Zhongyuan
> > > >
> > > > ?2009?12?17??07:02?Jack Schwartz???
> > > >
> > > >
> > > > > Hi Zhongyuan.
> > > > >
> > > > > Thanks for your feedback. Here's my assessment of requirements, based
> > > > > on both of our emails, and a new proposal which I believe addresses
> > > > > both
> > > > > of our needs and concerns. Hopefully it is not too long...
> > > > >
> > > > > A) You need a way to easily restrict the output to a given device
> > > > > type.
> > > > > I assume this why you proposed a dictionary keyed to the device type,
> > > > > at the top level. I didn't account for that in my original proposal.
> > > > >
> > > > > B) My proposal placed more of an emphasis on readability and clarity.
> > > > > This is why I originally proposed to store a device's attributes in a
> > > > > dictionary: attributes could be extracted by name.
> > > > >
> > > > > Additional requirements, as I see things:
> > > > >
> > > > > C) We don't want to make the data structures too complicated from a
> > > > > data
> > > > > access perspective. For example a dictionary of lists of dictionaries
> > > > > makes the code hard to follow.
> > > > >
> > > > > D) We don't want to introduce unnecessary overhead. If we can use
> > > > > something more lightweight than a dictionary and still have the
> > > > > functionality we need, then I would favor not using the dictionary.
> > > > >
> > > > >
> > > > > ddu_devscan() will be returning a group of items corresponding to
> > > > > devices, so it is appropriate to use a collection of some kind for the
> > > > > top level data structure it returns. At first I agreed with you that
> > > > > a
> > > > > dictionary would be best at the top level:
> > > > > - its items are named (via a key),
> > > > > - it can filter out unwanted items,
> > > > > - it doesn't have to keep a place for items it doesn't need.
> > > > > However, after thinking more, this could prove restrictive in the
> > > > > future. We return lots of information for each device, any of which
> > > > > could potentially be used as a filter for returning data. If the
> > > > > dictionary is keyed on device type and later we decide we need to
> > > > > filter on something else (or perhaps multiple items), say vendor ID
> > > > > and/or device ID, we're not set up for that.
> > > > >
> > > > > Instead, I propose a new class, call it devscan_data, which stores the
> > > > > full list of items returned by ddu_devscan() and has a method for
> > > > > searching and returning only items of a particular device type. Then
> > > > > in the future we could add other methods to support returning items
> > > > > based on some other filter criteria. It is also lightweight and
> > > > > provides only the functionality needed.
> > > > >
> > > > > What are the devscan_data list items? They would store the different
> > > > > fields of data per device. The list could point to dictionaries as I
> > > > > had originally proposed, to tuples as you have proposed, or to
> > > > > something
> > > > > else. I have changed my mind about dictionaries, and think they are
> > > > > the
> > > > > wrong tool; the number and type of fields will not change from one
> > > > > device to the next. I also still don't like tuples as the fields are
> > > > > hard to keep track of. Named tuples are better, but more heavyweight
> > > > > than if we defined a new class to hold the data. So I propose a new
> > > > > class, which would have attributes and get() methods for each field we
> > > > > want to return. Let's call it dev_data for now.
> > > > >
> > > > > To summarize:
> > > > >
> > > > > ddu_devscan() would return a devscan_data object defined like this:
> > > > >
> > > > > class devscan_data():
> > > > >
> > > > > def __init__()
> > > > > # Holds objects of dev_data.
> > > > > self.dev_data_list = []
> > > > >
> > > > > def add_dev_data_object(dev_data):
> > > > > self.dev_data_list.append(dev_data)
> > > > >
> > > > > def get_list_by_devtype(device_type):
> > > > > # loop through instance list data to find and return matches
> > > > > on
> > > > > # device_type
> > > > >
> > > > > Lists returned by get_list_by_devtype() point to objects of type
> > > > > dev_data.
> > > > > There is one of these objects per device returned.
> > > > >
> > > > > class dev_data:
> > > > >
> > > > > def __init__(...):
> > > > > self.device_type = ...
> > > > > self.description = ...
> > > > > self.driver_name
> > > > > self.instance_ID
> > > > > self.item_ID
> > > > > self.parent_item_ID
> > > > > self.attach_status
> > > > > self.vendor_id
> > > > > self.device_id
> > > > > self.class_code
> > > > > self.pci_path
> > > > >
> > > > > def get_device_type():
> > > > > return self.device_type
> > > > >
> > > > > def get_description():
> > > > > return self.description
> > > > >
> > > > > ...
> > > > > ...
> > > > >
> > > > > def get_pci_path:
> > > > > return self.pci_path
> > > > >
> > > > > Does this work for you?
> > > > >
> > > > > Thanks,
> > > > > Jack
> > > > >
> > > > > On 12/15/09 21:56, zhongyuan sun - Sun Microsystems - Beijing China
> > > > > wrote:
> > > > >
> > > > >
> > > > > > Hi Jack,
> > > > > >
> > > > > > It's OK ddu_devscan return dictionary type instead of a list of
> > > > > > tuples.
> > > > > > I suggest use device type as this dictionary's key and the
> > > > > > dictionary's
> > > > > > value would be a list of tuples.
> > > > > >
> > > > > > ddu_devscan description would be as following:
> > > > > >
> > > > > > Arguments:
> > > > > > - return_missing_only: Boolean; default value is True
> > > > > > - When True, ddu_devscan returns only the devices which are
> > > > > > missing
> > > > > > drivers.
> > > > > > - When False, all devices found are returned.
> > > > > > - device_type: Type of devices to scan for. "All" to check all.
> > > > > > - Possible types
> > > > > > are:"audio"/"battery"/"cpu"/"cd_dvd"/"memory"/"network"/"storage"/"usb"/"video"/"others"
> > > > > >
> > > > > >
> > > > > > In each tuple of the list:
> > > > > > - ItemID:
> > > > > > - Parent Item ID:
> > > > > > /*these two fields(ItemID and Parent Item ID) used for device
> > > > > > tree to
> > > > > > identify a device and the controller it attached to. Of
> > > > > > course for a
> > > > > > controller we do not need to set its parent Item ID.
> > > > > > */
> > > > > > - Device description:Device name
> > > > > > - Device ID:
> > > > > > - Classcode:
> > > > > > - PCI physical path:This field used to get its detail information.
> > > > > > - Driver name:
> > > > > > - Instance ID:
> > > > > > - Attachment status:
> > > > > > /*These two fields(Instance ID and Attachment status) used for
> > > > > > determine whether a driver
> > > > > > has been attached abnormally.
> > > > > > */
> > > > > > - Vendor ID
> > > > > >
> > > > > >
> > > > > > Here is a short example of ddu_devscan return value:
> > > > > >
> > > > > >
> > > > > >
> > > > > > > > > {'Audio': [(200,"","nVidia Corporation MCP55 High Definition
> > > > > > > > >
> > > > > > > > >
> > > > > > > > >
> > > > > > Audio","0x0371","00040300","[0,6,1]","unknown",-1,"Detached","0x10de")],'Network':[(0,"","nVidia
> > > > > > Corporation MCP55
> > > > > > Ethernet","0x0373","00068000","[80,8,0]","nge",0,"Attached","0x10de"),(1,"","nVidia
> > > > > > Corporation MCP55
> > > > > > Ethernet","0x0373","00068000","[80,9,0]","nge",1,"Attached","0x10de")],'DVD':[(400,"","nVidia
> > > > > > Corporation MCP55
> > > > > > IDE","0x036e","0001018a","[0,4,0]","pci-ide",0,"Attached","0x10de"),(401,400,"MATSHITA
> > > > > > DVD-RAM UJ-85JS","","","/pci at 0,0/pci-ide at 4/ide at 0/sd at
> > > > > > 0,0","sd",0,"Attached","")]}
> > > > > >
> > > > > >
> > > > > > I also would like to discuss with you a issue during scan process.
> > > > > > When
> > > > > > user kill GUI during scan process, some backround scripts will
> > > > > > still be
> > > > > > running even GUI thread has been killed, these scripts was created
> > > > > > when
> > > > > > performing scanning. Our solution was send a SIGUSR2 signal when GUI
> > > > > > want to kill its child processes. While if we wrapped our scripts
> > > > > > into
> > > > > > ddu_devscan, how can this function send a signal to its child
> > > > > > processes?
> > > > > > can we add a argument for this?
> > > > > >
> > > > > >
> > > > > > Thanks,
> > > > > > Zhongyuan
> > > > > >
> > > > > > ?2009?12?15??06:43?Jack Schwartz???
> > > > > >
> > > > > >
> > > > > >
> > > > > > > Hi Zhongyuan.
> > > > > > >
> > > > > > > Thanks for reviewing the interface spec. Moving to public forum.
> > > > > > >
> > > > > > > > I've some comments on DDU library API--ddu_devscan() function.
> > > > > > > > You've expanded this function to involve all devices found,
> > > > > > > it's
> > > > > > > > good! While for the Return value, currently it only includes
> > > > > > > > "compatible name" and "device descriptor" strings, It's not
> > > > > > > > sufficient especially for GUI part:
> > > > > > > >
> > > > > > > > *For non-mission items
> > > > > > > > (1)If the driver works fine,we need a "driver name" field.
> > > > > > > >
> > > > > > > OK
> > > > > > >
> > > > > > > > (2)If the driver dos not works fine, wee need the driver
> > > > > > > instance
> > > > > > > > ID and attachment status for this driver.
> > > > > > > >
> > > > > > > > Instance ID is a number get from system when driver attached.
> > > > > > > If
> > > > > > > > you have 2 e1000g nic cards and they all have been attached
> > > > > > > > properly, then they will get instance 0 and 1, while if the
> > > > > > > driver
> > > > > > > > have not been attached properly or device have been installed
> > > > > > > > properly, the instance ID will be <0 and attachment status
> > > > > > > will be
> > > > > > > > "detached".
> > > > > > > >
> > > > > > > > DDU GUI version used "instance ID" and attachment status to
> > > > > > > give
> > > > > > > > user a notification "driver missconfigured".
> > > > > > >
> > > > > > > OK
> > > > > > >
> > > > > > > >
> > > > > > > > BTW, for both non-missing and missing device, I hope we can add
> > > > > > > > "device category" argument to ddu_devscan function to indicate
> > > > > > > what
> > > > > > > > type of category will be looked for(like "Audio"/"Network"
> > > > > > > etc). By
> > > > > > > > default this argument can be set to "All" to look for all
> > > > > > > types of >
> > > > > > > device.
> > > > > > >
> > > > > > > OK.
> > > > > > >
> > > > > > > > For both missing and non-missing items, we also need these
> > > > > > > fields
> > > > > > > > at least:
> > > > > > > > (1)"Vendor id"/"device id"/"classcode" to identify which
> > > > > > > category
> > > > > > > > this device belongs to.
> > > > > > >
> > > > > > > OK.
> > > > > > >
> > > > > > > > (2)pci path to indicate this device's detail information.
> > > > > > > > Hopefully this can be involved into ddu_devscan function.
> > > > > > >
> > > > > > > OK.
> > > > > > >
> > > > > > > These are a lot of changes for ddu_devscan() for the GUI. I
> > > > > > > propose
> > > > > > > that ddu_devscan returns a list of dictionaries rather than a
> > > > > > > list of
> > > > > > > tuples (as before). Dictionaries because there are a lot of
> > > > > > > items
> > > > > > > returned. Also, not all fields will be used for all devices.
> > > > > > > (For
> > > > > > > example, the driver_name field won't be used when a device is
> > > > > > > missing).
> > > > > > >
> > > > > > > So this would translate into adding a signature of ddu_devscan()
> > > > > > > as follows:
> > > > > > >
> > > > > > > Arguments:
> > > > > > > - return_missing_only: Boolean; default value is True
> > > > > > > - When True, ddu_devscan returns only the devices which are
> > > > > > > missing
> > > > > > > drivers.
> > > > > > > - When False, all devices found are returned.
> > > > > > > - device_type: Type of devices to scan for. "All" to check all.
> > > > > > >
> > > > > > > ===> Please send the list of device types which are valid.
> > > > > > > "Audio" and
> > > > > > > "Network" were mentioned earlier.
> > > > > > >
> > > > > > > Returns:
> > > > > > > A list of dictionaries, each dictionary representing a device.
> > > > > > > List can
> > > > > > > be empty (possible only when Return_missing_only is True) to
> > > > > > > represent a
> > > > > > > system with no missing drivers.
> > > > > > >
> > > > > > > Items in each dictionary are:
> > > > > > >
> > > > > > > - compatible: device compatible name string, a space-separated
> > > > > > > string of
> > > > > > > all compatible names for a device. Compatible names in the
> > > > > > > string are
> > > > > > > ordered from the most specific name to the most general name
> > > > > > > (i.e. the
> > > > > > > "pciclass" definitions are listed last).
> > > > > > > - It is OK if two list items have one or more compatible
> > > > > > > names in common, but each list item should be unique.
> > > > > > >
> > > > > > > - description: Device description. can be used for error
> > > > > > > messages and
> > > > > > > status reporting.
> > > > > > >
> > > > > > > - device_type: Type of device (e.g. "Audio", "Network")
> > > > > > >
> > > > > > > - driver_name: Name of the driver operating the device. (Can be
> > > > > > > omitted
> > > > > > > if driver is missing.)
> > > > > > >
> > > > > > > - instance_ID: Instance ID assigned to the device. (Always
> > > > > > > present.
> > > > > > > Will be <0 if no driver is attached to the device.)
> > > > > > >
> > > > > > > - attach_status: Status of whether or not a driver is attached to
> > > > > > > the
> > > > > > > device. (Always present. Will be "detached" if driver is not
> > > > > > > attached,
> > > > > > > "attached" if driver is attached.
> > > > > > >
> > > > > > > ===> Any other statuses possible?
> > > > > > >
> > > > > > > - vendor_id: Device's vendor ID. (Always present.)
> > > > > > >
> > > > > > > - device_id: Device's device ID (Always present.)
> > > > > > >
> > > > > > > - class_code: Device's class code (Always present.)
> > > > > > >
> > > > > > > - pci_path: Device path (Always present.)
> > > > > > >
> > > > > > > Please let me know by today COB (PRC time) the device types and
> > > > > > > if any
> > > > > > > corrections are needed.
> > > > > > >
> > > > > > > Thanks,
> > > > > > > Jack
> > > > > > >
> > > > > > > On 12/04/09 09:20, Jack Schwartz wrote:
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > Hi everyone.
> > > > > > > >
> > > > > > > > FYI: Driver Update functional and programming interface specs
> > > > > > > > have had
> > > > > > > > a minor update. The items addressed deal either with
> > > > > > > > subtleties
> > > > > > > > missed during the main review but which came up during
> > > > > > > > development, or
> > > > > > > > other things we discovered were needed during development.
> > > > > > > >
> > > > > > > > Functional spec:
> > > > > > > > - Clarify that any repo can be specified, not only repos which
> > > > > > > > a
> > > > > > > > system already
> > > > > > > > knows about.
> > > > > > > > - Clarify that it is an error if a publisher name is already
> > > > > > > > mapped to
> > > > > > > > a repo,
> > > > > > > > and another repo with the same publisher name is requested.
> > > > > > > > - Add publisher to AI searchall capability
> > > > > > > >
> > > > > > > > Interface spec:
> > > > > > > > - Add arg to ddu_devscan() so that the function can return
> > > > > > > > either all
> > > > > > > > devices
> > > > > > > > on a system, or only devices which are missing their driver.
> > > > > > > >
> > > > > > > > Links on the Driver Update page have been updated. Previous
> > > > > > > > spec
> > > > > > > > versions have been retained on that page for comparison
> > > > > > > > purposes.
> > > > > > > >
> > > > > > > > Driver update page is at:
> > > > > > > > http://hub.opensolaris.org/bin/view/Project+caiman/Driver_Update
> > > > > > > >
> > > > > > > > If there are any questions or comments please send them my way.
> > > > > > > >
> > > > > > > > Thanks,
> > > > > > > > Jack
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> >
>
>
>
> ______________________________________________________________________
> #!/bin/ksh
>
> #
> # Child part
> #
> if [ "$1" == "child" ] ; then
> $0 grandchild &
> $0 grandchild &
> echo "Hi from child with pid $$"
> sleep 1000
> echo "Bye from child with pid $$"
> exit 0
> fi
>
> #
> # Grandchild part
> #
> if [ "$1" == "grandchild" ] ; then
> echo "Hi from grandchild with pid $$"
> sleep 1000
> echo "Bye from grandchild with pid $$"
> exit 0
> fi
>
> #
> # Parent part
> #
>
> #---------------
> function handler
> #---------------
> {
> echo "Terminating all child processes in this group ($$)..."
>
> # Catch the signal we're about to send out, so that I don't terminate by it.
> # Needed to prevent recursion if this handler is called when TERM received
> # (see "trap handler" line in main below)
> trap "" TERM
>
> # Send out the signal.
> pkill -TERM -g $$
>
> # Now perform any other cleanup I have to do.
> echo "Check for un-killed children..."
> echo "There should be only this process with PID $$ showing..."
> ps -efjl | head -1
> ps -efjl | grep $$ | grep -v grep | grep -v efjl
> echo "Handler Bye from parent"
> exit 0
> }
>
> #-----
> # Main
> #-----
>
> # Catch ^C, ^\ and regular "kill"
> trap handler INT QUIT TERM
>
> # Call this script with "child" as first arg to spawn child processes
> $0 child &
> $0 child &
> sleep 1000
> echo "Normal Bye from parent" # This won't execute if handler terminates me.
> exit 0
>
> ______________________________________________________________________
> #!/bin/python2.6
>
> import sys
> import subprocess
> import os
> import signal
> import time
>
> from subprocess import PIPE as PIPE
>
> #--------------------------
> def handler(signum, frame):
> #--------------------------
> print ("Terminating all child processes in this group (" +
> str(os.getpid()) + ") ...")
>
> # Catch the signal we're about to send out, so that I don't terminate by
> it.
> # Needed to prevent recursion if this handler is called when TERM received
> # (see "trap handler" line in main below)
> signal.signal(signal.SIGTERM, signal.SIG_IGN)
>
> # Send out the signal.
> subprocess.Popen(["/bin/pkill", "-TERM", "-g", str(os.getpid())])
>
> # Now perform any other cleanup I have to do.
> print "Check for un-killed children..."
> print ("There should be only this process with PID " +
> str(os.getpid()) + " showing...")
> # subprocess.Popen(["/bin/ps", "-efjl", "|", "head", "-1", ";",
> # "/bin/ps", "-efjl", "|", "grep", str(os.getpid()),
> "|",
> # "grep", "-v", "grep", "|", "grep", "-v", "efjl"],
> # shell=True)
> p1 = subprocess.Popen(["/bin/ps", "-efjl"], stdout=PIPE)
> p2 = subprocess.Popen(["head", "-1"], stdin=p1.stdout)
> p2.wait()
> p1 = subprocess.Popen(["/bin/ps", "-efjl"], stdout=PIPE)
> p2 = subprocess.Popen(["grep", str(os.getpid())], stdin=p1.stdout,
> stdout=PIPE)
> p3 = subprocess.Popen(["grep", "-v", "grep"], stdin=p2.stdout,
> stdout=PIPE)
> p4 = subprocess.Popen(["grep", "-v", "efjl"], stdin=p3.stdout)
> p4.wait()
> print "Handler Bye from parent"
> sys.exit(0)
>
>
> #--------------
> def main(argv):
> #--------------
> full_pathname = os.getcwd() + "/" + argv[0].rsplit("/",1)[1]
>
> #
> # Child part
> #
> if ((len(argv) > 1) and (argv[1] == "child")):
> subprocess.Popen([full_pathname, "grandchild"])
> subprocess.Popen([full_pathname, "grandchild"])
> print "Hi from child with pid " + str(os.getpid())
> time.sleep(1000)
> print "Bye from child with pid " + str(os.getpid())
> sys.exit(0)
>
> #
> # Grandchild part
> #
> if ((len(argv) > 1) and (argv[1] == "grandchild")):
> print "Hi from grandchild with pid " + str(os.getpid())
> time.sleep(1000)
> print "Bye from grandchild with pid " + str(os.getpid())
> sys.exit(0)
>
> #
> # Parent part
> #
>
> # Catch ^C, ^\ and regular "kill"
> signal.signal(signal.SIGINT, handler)
> signal.signal(signal.SIGQUIT, handler)
> signal.signal(signal.SIGTERM, handler)
>
> # Call this script with "child" as first arg to spawn child processes
> subprocess.Popen([full_pathname, "child"])
> subprocess.Popen([full_pathname, "child"])
> time.sleep(1000)
> print "Normal Bye from parent" # This won't execute if handler terminates
> me
> sys.exit(0)
>
> if __name__ == "__main__":
>
> try:
> main(sys.argv)
> except (SystemExit, KeyboardInterrupt):
> pass
>