Mandalika's scratchpad [ Work blog @Oracle | Stock Market Notes | My Music Compositions ]

Old Posts: 09.04  10.04  11.04  12.04  01.05  02.05  03.05  04.05  05.05  06.05  07.05  08.05  09.05  10.05  11.05  12.05  01.06  02.06  03.06  04.06  05.06  06.06  07.06  08.06  09.06  10.06  11.06  12.06  01.07  02.07  03.07  04.07  05.07  06.07  08.07  09.07  10.07  11.07  12.07  01.08  02.08  03.08  04.08  05.08  06.08  07.08  08.08  09.08  10.08  11.08  12.08  01.09  02.09  03.09  04.09  05.09  06.09  07.09  08.09  09.09  10.09  11.09  12.09  01.10  02.10  03.10  04.10  05.10  06.10  07.10  08.10  09.10  10.10  11.10  12.10  01.11  02.11  03.11  04.11  05.11  07.11  08.11  09.11  10.11  11.11  12.11  01.12  02.12  03.12  04.12  05.12  06.12  07.12  08.12  09.12  10.12  11.12  12.12  01.13  02.13  03.13  04.13  05.13  06.13  07.13  08.13  09.13  10.13  11.13  12.13  01.14  02.14  03.14  04.14  05.14  06.14  07.14  09.14 


Thursday, June 30, 2005
 
Solaris: Tip - Splitting and Merging Files

Sometimes we may have to split a large file into several small files before transfering 'em to another host. Later we can assemble these small files to re-create the original large file at the destination.

Splitting can be done on any file type, including binary files, with the help of split utility of Solaris. Read the man page of split, for all the available options. In the example, we will be using the following options to split one 11M file into several 2M files.

Syntax:
split [-b nm] [file [name]]

where:
-b nm suggests splitting a file into pieces of size nMB, with the name to be used for each of the files resulting from the split operation.

split will append something like "aa", "ab", etc., to make the resulting file names unique and in ascending sort order.

eg., 1. Splitting a large file
% ls -lh *.zip
-rw-r--r-- 1 giri other 11M Jun 30 12:10 src.zip

% split -b 3m src.zip source

% ls -lh source*
-rw-rw-r-- 1 giri other 3.0M Jun 30 17:18 sourceaa
-rw-rw-r-- 1 giri other 3.0M Jun 30 17:18 sourceab
-rw-rw-r-- 1 giri other 3.0M Jun 30 17:18 sourceac
-rw-rw-r-- 1 giri other 2.3M Jun 30 17:18 sourcead

2. Re-creating the original file (assembling) from small files

Since the same file has been split into small files sequentially, we can use cat to merge the small files. If the number files to merge is small, then it is easy to use cat and redirecting the output to a file.
eg.,
  1. One file at a time
    % cat sourceaa > CopyOfsrc.zip
    cat sourceab >> CopyOfsrc.zip
    cat sourceac >> CopyOfsrc.zip
    cat sourcead >> CopyOfsrc.zip
  2. All files at once
    % cat source* > CopyOfsrc.zip
  3. Some problems with above mentioned approaches:
    1. will be inconvenient to redirect the output to a file, if the number of files are too many (approach #1)
    2. may fail, with Arguments too long error, depending on the shell, if the number of files are too many (approach #2)

    • Workaround:
      Use the combination of cat and xargs
        xargs reads a group of arguments from its standard input, then runs a UNIX command with that group of arguments. It keeps reading arguments and running the command until it runs out of arguments. So, it is very unlikely to hit the limitations of a shell and Arguments too long error

      eg.,
      % ls source* | xargs cat > CopyOfsrc.zip.
      Since ls lists all the small files in sorted order, we don't have to worry about merging the files in correct order.
% ls -lh CopyOfsrc.zip
-rw-rw-r-- 1 giri other 11M Jun 30 17:57 CopyOfsrc.zip

% file CopyOfsrc.zip
CopyOfsrc.zip: ZIP archive
Verify the checksum of both the files:
% cksum CopyOfsrc.zip
1904556195 11875601 CopyOfsrc.zip

% cksum src.zip
1904556195 11875601 src.zip
Note:
The resulting files from split, will be stored in the same format as original. In our example, all sourcexy files will be of type "zip archive". But since they are not complete, trying to extract the files results in an error.
% file sourceaa
sourceaa: ZIP archive

% unzip sourceaa
Archive: sourceaa
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of sourceaa or
sourceaa.zip, and cannot find sourceaa.ZIP, period.

________________
Technorati tags: |


Thursday, June 23, 2005
 
Solaris: (Undocumented) Thread Environment Variables

The new thread library (initially called T2) on Solaris 8 Update 7 and later versions of Solaris, provides a 1:1 threading model, for better performance and scalability. Just like other libraries of Solaris, the new thread library is binary compatible with the old library, and the applications linked with old library continue to work as they are, without any changes to the application or any need to re-compile the code.

The primary difference being the new thread library uses a 1:1 thread model, where as the old library implements a two-level model in which user-level threads are multiplexed over possibly fewer light weight processes. In the 1:1 (or 1x1) model, an user level (application) thread has a corresponding kernel thread. A multi-threaded application with n threads will have n kernel threads. Each user level thread has a light weight process (LWP) connecting it to the kernel thread. Due to the more number of LWPs, the resource consumption will be a little high with 1x1 model, compared to MxN model; but due to the less overhead of multiplexing and scheduling the threads over LWP, 1x1 model performs much better compared to the old MxN model.

Tuning an application with thread environment variables

Within the new thread library (libthread) framework, a bunch of tunables have been provided to tweak the performance of the application. All these tunables have default values, and often the default values are good enough for the application to perform better. For some unknown reasons, these tunables were not documented anywhere except in source code. You can have a look at the source code for the following files at OpenSolaris
Here's a brief description of these environment variables along with their default values:
  1. LIBTHREAD_QUEUE_SPIN

    • Controls the spinning for queue locks
    • Default value: 1000

  2. LIBTHREAD_ADAPTIVE_SPIN

    • Specifies the number of iterations (spin count) for adaptive mutex locking before giving up and going to sleep
    • Default value: 1000

  3. LIBTHREAD_RELEASE_SPIN

    • Spin LIBTHREAD_RELEASE_SPIN times to see if a spinner grabs the lock; if so, don’t bother to wake up a waiter
    • Default value: LIBTHREAD_ADAPTIVE_SPIN/2 ie., 500. However it can be set explicitly to override the default value

  4. LIBTHREAD_MAX_SPINNERS

    • Limits the number of simultaneous spinners attempting to do adaptive locking
    • Default value: 100

  5. LIBTHREAD_MUTEX_HANDOFF

    • Do direct mutex handoff (no adaptive locking)
    • Default value: 0

  6. LIBTHREAD_QUEUE_FIFO

    • Specifies the frequency of FIFO queueing vs LIFO queueing (range is 0..8)
    • Default value: 4
    • LIFO queue ordering is unfair and can lead to starvation, but it gives better performance for heavily contended locks

      • 0 - every 256th time (almost always LIFO)
      • 1 - every 128th time
      • 2 - every 64th time
      • 3 - every 32nd time
      • 4 - every 16th time (default, mostly LIFO)
      • 5 - every 8th time
      • 6 - every 4th time
      • 7 - every 2nd time
      • 8 - every time (never LIFO, always FIFO)

  7. LIBTHREAD_QUEUE_DUMP

    • Causes a dump of user−level sleep queue statistics onto stderr (file descriptor 2) on exit
    • Default value: 0

  8. LIBTHREAD_STACK_CACHE

    • Specifies the number of cached stacks the library keeps for re−use when more threads are created
    • Default value: 10

  9. LIBTHREAD_COND_WAIT_DEFER

    • Little bit of history:

      The old thread library (Solaris 8's default) forces the thread performing cond_wait() to block all signals until it reacquires the mutex.

      The new thread library on Solaris 9 (default) and later versions, behaves exact opposite. The state of the mutex in the signal handler is undefined and the thread does not block any more signals than it is already blocking on entry to cond_wait().

      However to accomodate the applications that rely on old behavior, the new thread library implemented the old behavior as well, and it can be controlled with the LIBTHREAD_COND_WAIT_DEFER env variable. To get the old behavior, this variable has to be set to 1.

  10. LIBTHREAD_ERROR_DETECTION

    • Setting it to 1 issues a warning message about illegal locking operations and setting it to 2 issues the warning message and core dump
    • Default value: 0

Reference:
Roger Faulkner's New/Improved Threads Library presentation

________________
Technorati tags: |


Monday, June 20, 2005
 
Solaris 10: USB Digital Camera HOWTO

The following instructions are very "generic", and applicable to all makes/models of digital cameras. Sony DSC-V1 camera was used to show all the examples.

Since the vendor supplied Windows driver cannot be installed on Solaris, it needs some effort to make the digital camera work on Solaris 10. The steps are as follows:
Note that this is a one time only effort, and these steps need not be repeated everytime the digital camera has been plugged in to the system.

References and suggested reading:
  1. Solaris USB FAQ
  2. Dan Price's blog post - gtkam & USB on Solaris 10
  3. Ben Rockwood's blog post - Canon Rebel XT on OpenSolaris
  4. White Paper: Using the USB Generic Driver (Ugen) to Access USB Peripherals on Solaris Systems
Related blog entry:
JDS Linux & Sony DSC-V1/W1 Digital Camera

Thanks to fritS of Sun Microsystems, for his notes on using gphoto2 and gtkam with your digital camera

Technorati tags:


Tuesday, June 14, 2005
 
OpenSolaris: Open for download

The much awaited OpenSolaris has finally arrived. Too bad it cannot be treated as a vaporware anymore. I believe the following resources are helpful for those, who are completely new to Solaris/OpenSolaris.

OpenSolaris:
OpenSolaris community web site
OpenSolaris release notes
OpenSolaris source browser
Download OpenSolaris source code OpenSolaris bug database
OpenSolaris roadmap
OpenSolaris community tools (Sun Studio 10, GCC compilers)

License:
Common Development and Distribution License (CDDL)

Documentation:
CuddleTech's HowTo: Building OpenSolaris
CuddleTech's OpenSolaris developers reference
OpenSolaris: Getting started documents
Summary of OpenSolaris features with examples

Technical content (community web sites and blog posts):
Sun blogs
Planet Solaris
Planet Sun
Jim Grisanzio's cool collection of Solaris community blogroll
GenUnix.Org - an OpenSolaris community web site

Discussion Groups:
Solaris x86 Yahoo group
OpenSolaris Google group
Solaris Google group
Western PA OpenSolaris Users Group

IRC:
Network: irc.freenode.net
Channels: #opensolaris, #solaris

Distros:
  1. SchilliX Live CD
    SchilliX Home Page | Download SchilliX ISO | SchilliX distro README
  2. Blastware's Polaris [Updated: 04/12/07] MarTux, distribution for SPARC platform
  3. RobustaOS
  4. BeleniX
  5. Nexenta with Debian packaging tools; and Ubuntu look and feel
  6. [Updated: 04/12/07] Singanix for servers

Other resources:
Technorati's OpenSolaris page
del.icio.us' OpenSolaris page
________________
Technorati tags: ,


Sunday, June 12, 2005
 
C/C++: Assertions

What is an assertion?

An assertion is a statement that can be used to test our assumptions about certain parts of the program. It is a boolean expression, and by placing an assertion, we expect it to return true. Placing assertions in the code increases the robustness of the code by letting the programmer catch the logic errors in the early stages of the development. If the assertion returns true, it confirms that the assumptions about the behavior of the program is right. Otherwise, the system throws an error.

Pre-, Post-conditions

Assertions are generally useful for testing the pre- and post-conditions of a routine.

A pre-condition specifies what must be true when a routine is invoked. ie., it is a statement by the programmer that a given routine should not be entered unless its pre-condition is guaranteed. If it is entered anyway, the routine may behave erratically. In general, pre-conditions depend on global variables and input arguments.

A post-condition specifies what must be true after a routine completes successfully.

Example:
If the pre-condition for a function requires the age of a person to be > 25 years, we can place an assertion like the following as the very first line of the function:

assert (age > 25);

If any value <= 25 is passed as input to the function, the assertion statement halts the execution of the program and triggers an error Assertion Failed.

Full source (very trivial - just to introduce assert() routine of Standard C library):
% cat assert.c

#include <stdio.h>
#include <assert.h>

bool checkEligibility (int age, int salary) {
assert (age > 25);
if (salary > 5000) {
return (true);
} else {
return (false);
}
}

int main() {
int age = 23, salary = 7750;
bool eligible = false;

eligible = checkEligibility (age, salary);
if (eligible) {
printf("\nThis person is eligible for ..");
} else {
printf("\nThis person is not eligible for ..");
}
return (0);
}

% CC -o assert assert.c
% ./assert
Assertion failed: age > 25, file assert.c, line 5
Abort (core dumped)

And here's the corresponding stack trace:
(dbx) where                                                                  
=>[1] _lwp_kill(0x1, 0x6), at 0xd258e875
[2] _pthread_kill(0x1, 0x6), at 0xd258b71b
[3] raise(0x6), at 0xd253adbb
[4] abort(0x8046fc8,0xd27fb824,0x65737341,0x6f697472,0x6166206e,0x64656c69), at 0xd251e909
[5] __assert(0x8050ba4, 0x8050bad, 0x5), at 0xd251eb23
[6] checkEligibility(0x17, 0x1e46), at 0x805098e
[7] main(0x1, 0x804700c, 0x8047014), at 0x8050a22

The above example tests only for a pre-condition with an assertion. Similarly, assertion can be used for testing post-conditions as well. Note that assertions are not limited to pre- / post- conditions though they are used for testing those conditions in general. There are no restrictions on where to (and where not to) put the assertion statements in a program; they can be placed anywhere in the program just like any other statement.

Note:
It is a good practice to avoid writing assertions that have side effects.
eg.,
bool checkEligibility (int age, int salary) {
assert (age++ > 25);
...
}
In the above example, the assertion returns true even though 25 is passed as input for age.

Suggested Reading:
Practical Advice on Writing Pre- Post-Conditions for Real Programs by Prabhaker Mateti

Technorati tag:


Thursday, June 09, 2005
 
C/C++: conditional compilation and #if 0

It is a common practice to use compiler's preprocessor for conditional compilation. Conditional compilation is useful when the application has platform specific code, and if it has to be supported on more than one platform.

eg.,
#ifdef SOLARIS
Solaris specific code here
#else if defined (WIN32)
Windows specific code
#endif

Besides platform specific code, conditional compilation is useful in many ways. It is extremely useful to disable large chunks of code in a program. If we need to keep some code only for future reference Or if we need to disable certain parts of the program tentatively, we can use conditional compilation. The trick is to use #if 0 .. #endif directive over the block of code to be disabled. As 0 is always "not true" (ie., !1; 1 is always true) in computer programming, the block of code within #if 0 .. #endif gets never compiled.

eg.,
#if 0
/* the following code will not be compiled */
int x = 100, y = 200, z = -1;
z = x + y;
..
#endif // #if 0

The compilation succeeds even though the code being disabled contain other conditionals as long as they are balanced. ie., entire conditionals with balanced #if and #endifs.

Also it helps, if the code has C style comments (/* .. */') embedded in it. It is a known fact that C comments do not nest, and results in a compilation error if we try to do so.

Technorati tag:


Sunday, June 05, 2005
 
Solaris: Installing apps/packages with pkg-get

Often it is very frustrating to install software on *nix systems, and Solaris is no exception. Most of the times, non-availability of software in "ready to install" form, and/or the lack of installed dependencies on the local system, makes it even hard for the novice end-user. Wouldn't it be nice to have some kind of tool, that does the installation for us automatically, including dependencies (if any)? Fortunately, tools like apt-get, pkg-get do exist on some *nix environments, for automatic package installations.

apt-get (Advanced Package Tool) is available on some Linux distributions, quite for some time. For more on apt-get, have a look at the web page, APT HOWTO.

The following paragraphs concentrate on a similar tool, pkg-get for Solaris environment.

What is pkg-get?
(The following text was borrowed from bolthole.com; full-text can be viewed at: Solaris pkg-get tool):

pkg-get is a tool to automate download and installation of binary packages from archive sites that support it.

This tool simplifies fetching the latest version of a package from compatible sites to be as simple as:
% pkg-get install gcc

This will automatically download the appropriate version for your architecture and OS revision (if available), and install the package. If you have an older version of the package already installed, using 'upgrade' instead of 'install' will replace the older version with a newer one, if available.

If the archive supports dependancies, pkg-get will also download any needed dependancies. For example:
% pkg-get install mod_php
should triger an automatic
% pkg-get install apache
which in turn should automatically trigger
% pkg-get install openssl.
One of the sites that supports these dependancies is www.blastwave.org. Another one is www.sunfreeware.com. Rest of the instructions focus on installing pkg-get to get packages from blastwave.org. To get packages from sunfreeware.com, /etc/pkg-get.conf has to be modified as explained in the latter parts of "How to install pkg-get?" section.

How to install pkg-get?
(source: blastwave.org; full-text is at: http://www.blastwave.org/howto.html)
  1. Download pkg-get from http://www.blastwave.org/pkg_get.pkg. Since it is a package, it has to be installed with pkgadd command on Solaris.

    % pkgadd -d <path of pkg-get>/pkg-get.pkg
  2. Download and install a copy of wget
    Download locations:
    SPARC version: wget-sparc.bin
    x86 version : wget-i386.bin

    (From GNU wget FAQ) wget is a network utility to retrieve files from the World Wide Web using HTTP and FTP, the two most widely used Internet protocols. It works non-interactively, so it can work in the background, after having logged off. The program supports recursive retrieval of web-authoring pages as well as FTP sites - you can use wget to make mirrors of archives and home pages or to travel the Web like a WWW robot.

    This version of wget is simple, without any dependencies. But this copy is good enough to install the complete wget package as explained later.

    Make the wget, an executable and add it to the PATH environment variable. This step is very important for pkg-get to work properly. So, make sure you have wget in your PATH, before you move on to the next step.
  3. Make sure that you have both wget, and pkg-get in your PATH, with which wget, and which pkg-get commands.
  4. Edit pkg-get configuration file: /etc/pkg-get.conf file, to get software packages from a nearby source. You can find a list of Blastwave mirrors at: http://www.blastwave.org/mirrors.php.
  5. Install the complete wget package with the man pages and dependencies.

    % pkg-get -i wget. -i switch can be used to instruct pkg-get to install something.

    Now remove the simple wget that was installed in step (2).

    Add /opt/csw/bin at the beginning of PATH variable (the essential pkg-get & wget tools will reside under code>/opt/csw/bin directory.). Also add /opt/csw/man to the MANPATH to read the newly installed manual pages.

    man pkg-get is a good starting point to use pkg-get, conveniently.
Quick Reference
  1. pkg-get available, lists all the software that is available for download on the remote server. pkg-get compare is similar to pkg-get available, except that it shows the local status of the packages as well.
  2. A list of software descriptions can be viewed with pkg-get describe.
  3. You can search for software using regular expressions.
    eg.,
    -D is synonymous with describe
    % pkg-get -D '^g.. '
    # (Descriptions from site ibiblio.org )
    gdb - The GNU Debugger
    gm4 - GNU m4 Unix macro processor
    gtk - the Gimp ToolKit library, libgtk

  4. To install a package:
    pkg-get install <pkg> Or pkg-get -i <pkg>
    eg.,
    % pkg-get -i firefox
  5. To upgrade a package:
    pkg-get upgrade <pkg> Or pkg-get -U <pkg>
    eg.,
    % pkg-get -U firefox
Note:
pkg-get is a pure command line interface. If you are more used to Windows environment, you can try pkgadm tool from bolthole.com. More information is available at: Solaris pkgadm tool.

Acknowledgements & recommendations:
  1. bolthole.com
  2. blastwave.org
  3. sunfreeware.com
Technorati Tag:


Thursday, June 02, 2005
 
UNIX: Writing a Signal Handler

What is a signal?

A signal is a software interrupt, sent to a process to notify that an event has occured. Signals are usually sent by the Operating System (kernel) to notify processes that some event has occurred. Due to this, the processes need not poll for a particular event. By their nature, signals interrupt whatever the process is doing at that moment, and force it to handle them immediately. Because events may occur asynchronously, it is a good practice for the process to handle all the relevant signals using the API provided by the OS.

For example, the user may want to stop the process any time by pressing Control-C, which results in SIGINT signal.

Each signal has an integer number, as well as a symbolic name associated with it. Usually these are defined in /usr/include/sys/iso/signal_iso.h header file on Solaris. Note that we have to include /usr/include/signal.h file in our C/C++ programs, if we are going to use the signal API.

There are about 25 different kinds of signals, depending on the flavor of the system. Use the command kill -l, to get the list of signals supported by your system.

%uname -a
SunOS Govinda 5.9 Generic_118558-02 sun4u sparc SUNW,Ultra-Enterprise

% kill -l
HUP INT QUIT ILL TRAP ABRT EMT FPE
KILL BUS SEGV SYS PIPE ALRM TERM USR1
USR2 CLD PWR WINCH URG POLL STOP TSTP
CONT TTIN TTOU VTALRM PROF XCPU XFSZ WAITING
LWP FREEZE THAW CANCEL LOST XRES RTMIN RTMIN+1
RTMIN+2 RTMIN+3 RTMAX-3 RTMAX-2 RTMAX-1 RTMAX

For some signals, the default behavior is to ignore the signal. For others, the default behavior is to terminate the process.

Some terminating signals also produce the image of the memory layout (aka core) of the process when it was terminated. The core file will be useful for debugging. On Solaris, the behavior of all the signals was documented in /usr/include/sys/iso/signal_iso.h file.

The process can catch most of the signals except for a few. The process cannot catch SIGKILL & SIGSTOP signals. When the process receives such signals, it will be terminated.

If the program does not install any signal handlers, the run-time environment sets up a set of default signal handlers for the program. For example, the default signal handler for the TERM signal calls the exit() system call. The default handler for the ABRT is to dump the process's memory image into a file named core in the process's current directory, and then exit.

The signal handler is a function that gets called when the process receives a signal. The function is called in asynchronous mode, meaning that no where in the program you have code that calls this function directly. Instead, when the signal is sent to the process, the OS stops the execution of the process, and forces it to call the signal handler function. When the signal handler function returns, the process continues execution from wherever it happened to be before the signal was received. Failing to properly handle various signals, would likely cause our application to terminate, when it receives such signals.

The process can install its own signal handler to change the default behavior of any signal, except for SIGTERM.

Examples

Sending signals
---------------

Signals can be sent using keyboard (Ctrl-C, Ctrl-Z etc.,), command line with kill -<signal> <PID> (eg., kill -9 1234, kills the process with PID 1234) or using system calls.

The following C program shows how to send signals with kill() system call

% cat sendsignal.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>

int main() {
pid_t my_pid = getpid();
printf("\nMy process id (PID) = %d. Killing myself ..", my_pid);
kill(my_pid, SIGKILL);
return (0);
}

% cc -o sendsignal sendsignal.c
% ./sendsignal

My process id (PID) = 15031. Killing myself ..Killed


Simple signal handler
---------------------
The following trivial C program illustrates, how to write a simple signal handler

% cat signalhandler.c
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

/*
* signal handler
*/

void CatchInterrupt (int signum) {
pid_t my_pid;

printf("\nReceived an interrupt! About to exit ..\n");
fflush(stdout);
my_pid = getpid();
kill(my_pid, SIGKILL);
}

int main(int argc, char** argv) {
/*
* Set the INT (Ctrl-C) signal handler to 'CatchInterrupt'
*/
signal(SIGINT, CatchInterrupt);

/*
* Do Nothing and wait for interrupts
*/
for ( ;; ) {}
}

% cc -o signalhandler signalhandler.c

% ./signalhandler
^C
Received an interrupt! About to exit ..
Killed

In the above program, the process simply waits in an infinite loop, for an interrupt event to occur and as soon as it receive one, it exits after printing a message on the console.

Note:
If the process should not die, and has to handle the signal whenever the event occurs, we have to reset (reinstall) the signal handler in CatchInterrupt() for it to catch the interrupt signals further. The modified code will be like this:

/*
* signal handler
*/

void CatchInterrupt (int signum) {
/*
* Reset the signal handler to catch interrupt again
*/
signal(SIGINT, CatchInterrupt);
printf("\nReceived an interrupt! Waiting for further interrupt signals ..\n");
fflush(stdout);
}

The behavior will be like this, after compiling and executing the code:

%./signalhandler
^C
Received an interrupt! Waiting for further interrupt signals ..
^C
Received an interrupt! Waiting for further interrupt signals ..
^C
Received an interrupt! Waiting for further interrupt signals ..
^C
Received an interrupt! Waiting for further interrupt signals ..
^Z
Stopped (user)


Reference:
Introduction To Unix Signals Programming

Technorati tag:



2004-2014 

This page is powered by Blogger. Isn't yours?