classification
Title: multiple errors in test_socket on OpenBSD
Type: behavior Stage: resolved
Components: Versions: Python 3.2, Python 3.3
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: neologix, rpointel, vstinner
Priority: normal Keywords:

Created on 2011-09-05 21:33 by rpointel, last changed 2012-02-28 08:20 by neologix. This issue is now closed.

Files
File name Uploaded Description Edit
OpenBSD_test_socket_gdb.log rpointel, 2011-09-05 21:39 gdb output backtrace
Messages (18)
msg143564 - (view) Author: Remi Pointel (rpointel) * Date: 2011-09-05 21:33
Hi,

I have few problems in test_socket.py.

1) test_sendall_interrupted blocks on OpenBSD, I must Ctrl+c to interrupt the test. I added a skip to have full regress tests, but I think it's not the proper way.
I have run it into gdb, and ctrl+c it:
test_sendall_interrupted (__main__.GeneralModuleTests) ... [New process 20677]
^C
Program received signal SIGINT, Interrupt.
0x0000000206d2378a in poll () from /usr/lib/libc.so.60.1
(gdb) bt
#0  0x0000000206d2378a in poll () from /usr/lib/libc.so.60.1
#1  0x0000000205f4e4aa in _thread_kern_poll (wait_reqd=Variable "wait_reqd" is not available.
)
    at /usr/src/lib/libpthread/uthread/uthread_kern.c:780
#2  0x0000000205f4f3a8 in _thread_kern_sched (scp=0x0)
    at /usr/src/lib/libpthread/uthread/uthread_kern.c:382
#3  0x0000000205f43ade in sendto (fd=8, msg=0x2047bb040, len=1044480, flags=0, to=0x0, to_len=0)
    at /usr/src/lib/libpthread/uthread/uthread_sendto.c:63
#4  0x0000000210a5b243 in sock_sendall (s=0x20115c948, args=0x2011510d0)
    at /usr/ports/pobj/Python-3.2.2/Python-3.Modules/socketmodule.c:2699
#5  0x0000000000468992 in PyEval_EvalFrameEx (f=0x20a281c30, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:3921
#6  0x000000000046a95c in PyEval_EvalCodeEx (_co=0x20fc581b0, globals=Variable "globals" is not available.
) at Python/ceval.c:3350
#7  0x0000000000466df6 in PyEval_EvalFrameEx (f=0x20a9a3c30, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4019
#8  0x0000000000468c1a in PyEval_EvalFrameEx (f=0x2033af030, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4009
#9  0x000000000046a95c in PyEval_EvalCodeEx (_co=0x2028a9de8, globals=Variable "globals" is not available.
) at Python/ceval.c:3350
#10 0x0000000000466df6 in PyEval_EvalFrameEx (f=0x2052f1430, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4019
#11 0x000000000046a95c in PyEval_EvalCodeEx (_co=0x2028a9f58, globals=Variable "globals" is not available.
) at Python/ceval.c:3350
#12 0x0000000000511ce3 in function_call (func=0x2050d5620, arg=0x20115d330, kw=0x2052f0030)
    at Objects/funcobject.c:629
#13 0x00000000004e4a7f in PyObject_Call (func=0x2050d5620, arg=0x20115d330, kw=0x2052f0030)
    at Objects/abstract.c:2149
#14 0x000000000046456d in PyEval_EvalFrameEx (f=0x2052f0e30, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4236
#15 0x000000000046a95c in PyEval_EvalCodeEx (_co=0x2028ad268, globals=Variable "globals" is not available.
) at Python/ceval.c:3350
#16 0x0000000000511ce3 in function_call (func=0x2050d5790, arg=0x20115d240, kw=0x0)
    at Objects/funcobject.c:629
#17 0x00000000004e4a7f in PyObject_Call (func=0x2050d5790, arg=0x20115d240, kw=0x0)
    at Objects/abstract.c:2149
#18 0x00000000004ff349 in method_call (func=0x2050d5790, arg=0x20115a5a0, kw=0x0)
    at Objects/classobject.c:319
#19 0x00000000004e4a7f in PyObject_Call (func=0x20115d150, arg=0x20115a5a0, kw=0x0)
    at Objects/abstract.c:2149
#20 0x000000000042cb66 in slot_tp_call (self=Variable "self" is not available.
) at Objects/typeobject.c:5044
#21 0x00000000004e4a7f in PyObject_Call (func=0x20113b680, arg=0x20115a5a0, kw=0x0)
    at Objects/abstract.c:2149
#22 0x00000000004628fb in PyEval_EvalFrameEx (f=0x2071dc030, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4141
#23 0x000000000046a95c in PyEval_EvalCodeEx (_co=0x2086db6b8, globals=Variable "globals" is not available.
) at Python/ceval.c:3350
#24 0x0000000000511ce3 in function_call (func=0x2086de1d0, arg=0x20115d1c8, kw=0x2071dd430)
    at Objects/funcobject.c:629
#25 0x00000000004e4a7f in PyObject_Call (func=0x2086de1d0, arg=0x20115d1c8, kw=0x2071dd430)
    at Objects/abstract.c:2149
#26 0x000000000046456d in PyEval_EvalFrameEx (f=0x2071dde30, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4236
#27 0x000000000046a95c in PyEval_EvalCodeEx (_co=0x2086db490, globals=Variable "globals" is not available.
) at Python/ceval.c:3350
#28 0x0000000000511ce3 in function_call (func=0x2086de060, arg=0x20113f420, kw=0x0)
    at Objects/funcobject.c:629
#29 0x00000000004e4a7f in PyObject_Call (func=0x2086de060, arg=0x20113f420, kw=0x0)
    at Objects/abstract.c:2149
#30 0x00000000004ff349 in method_call (func=0x2086de060, arg=0x2011411b0, kw=0x0)
    at Objects/classobject.c:319
#31 0x00000000004e4a7f in PyObject_Call (func=0x20115d0d8, arg=0x2011411b0, kw=0x0)
    at Objects/abstract.c:2149
#32 0x000000000042cb66 in slot_tp_call (self=Variable "self" is not available.
) at Objects/typeobject.c:5044
#33 0x00000000004e4a7f in PyObject_Call (func=0x201138920, arg=0x2011411b0, kw=0x0)
    at Objects/abstract.c:2149
#34 0x00000000004628fb in PyEval_EvalFrameEx (f=0x2071dc430, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4141
#35 0x000000000046a95c in PyEval_EvalCodeEx (_co=0x2086db6b8, globals=Variable "globals" is not available.
) at Python/ceval.c:3350
#36 0x0000000000511ce3 in function_call (func=0x2086de1d0, arg=0x20113c498, kw=0x2071dd830)
    at Objects/funcobject.c:629
#37 0x00000000004e4a7f in PyObject_Call (func=0x2086de1d0, arg=0x20113c498, kw=0x2071dd830)
    at Objects/abstract.c:2149
#38 0x000000000046456d in PyEval_EvalFrameEx (f=0x2071dda30, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4236
#39 0x000000000046a95c in PyEval_EvalCodeEx (_co=0x2086db490, globals=Variable "globals" is not available.
) at Python/ceval.c:3350
#40 0x0000000000511ce3 in function_call (func=0x2086de060, arg=0x201127ee8, kw=0x0)
    at Objects/funcobject.c:629
#41 0x00000000004e4a7f in PyObject_Call (func=0x2086de060, arg=0x201127ee8, kw=0x0)
    at Objects/abstract.c:2149
#42 0x00000000004ff349 in method_call (func=0x2086de060, arg=0x20113e920, kw=0x0)
    at Objects/classobject.c:319
#43 0x00000000004e4a7f in PyObject_Call (func=0x208ba78d0, arg=0x20113e920, kw=0x0)
    at Objects/abstract.c:2149
#44 0x000000000042cb66 in slot_tp_call (self=Variable "self" is not available.
) at Objects/typeobject.c:5044
#45 0x00000000004e4a7f in PyObject_Call (func=0x201138370, arg=0x20113e920, kw=0x0)
    at Objects/abstract.c:2149
#46 0x00000000004628fb in PyEval_EvalFrameEx (f=0x20de7d830, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4141
#47 0x0000000000468c1a in PyEval_EvalFrameEx (f=0x20de7f830, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4009
#48 0x0000000000468c1a in PyEval_EvalFrameEx (f=0x20e626830, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4009
#49 0x000000000046a95c in PyEval_EvalCodeEx (_co=0x20189b040, globals=Variable "globals" is not available.
) at Python/ceval.c:3350
#50 0x0000000000511ce3 in function_call (func=0x20449fb28, arg=0x2071d9a30, kw=0x0)
    at Objects/funcobject.c:629
#51 0x00000000004e4a7f in PyObject_Call (func=0x20449fb28, arg=0x2071d9a30, kw=0x0)
    at Objects/abstract.c:2149
#52 0x000000000046456d in PyEval_EvalFrameEx (f=0x200eb9830, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4236
#53 0x0000000000468c1a in PyEval_EvalFrameEx (f=0x209c2d830, throwflag=Variable "throwflag" is not available.
) at Python/ceval.c:4009
#54 0x000000000046a95c in PyEval_EvalCodeEx (_co=0x20fc856b8, globals=Variable "globals" is not available.
) at Python/ceval.c:3350
#55 0x000000000046ab2b in PyEval_EvalCode (co=Variable "co" is not available.
) at Python/ceval.c:767
#56 0x000000000048ade7 in run_mod (mod=Variable "mod" is not available.
) at Python/pythonrun.c:1783
#57 0x000000000048aeee in PyRun_FileExFlags (fp=0x2071bb8e0, 
    filename=0x205619690 "Lib/test/test_socket.py.orig", start=257, globals=0x205a01e30, 
    locals=0x205a01e30, closeit=1, flags=0x7f7ffffbe5e0) at Python/pythonrun.c:1740
#58 0x000000000048da19 in PyRun_SimpleFileExFlags (fp=0x2071bb8e0, 
    filename=0x205619690 "Lib/test/test_socket.py.orig", closeit=1, flags=0x7f7ffffbe5e0)
    at Python/pythonrun.c:1265
#59 0x000000000049fe00 in Py_Main (argc=Variable "argc" is not available.
) at Modules/main.c:297
#60 0x0000000000414eaa in main (argc=2, argv=0x7f7ffffbe6a0) at ./Modules/python.c:59


2) test_sendall_interrupted_with_timeout has an error:
======================================================================
ERROR: test_sendall_interrupted_with_timeout (__main__.GeneralModuleTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "Lib/test/test_socket.py", line 753, in test_sendall_interrupted_with_timeout
    self.check_sendall_interrupted(True)
  File "Lib/test/test_socket.py", line 742, in check_sendall_interrupted
    self.assertRaises(socket.timeout, c.sendall, b"x" * (1024**2))
  File "/usr/ports/pobj/Python-3.2.2/Python-3.Lib/unittest/case.py", line 557, in assertRaises
    callableObj(*args, **kwargs)
socket.error: [Errno 0] Error
======================================================================

3) testInterruptedTimeout failed:
======================================================================
FAIL: testInterruptedTimeout (__main__.TCPTimeoutTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "Lib/test/test_socket.py", line 1707, in testInterruptedTimeout
    foo = self.serv.accept()
socket.timeout: timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "Lib/test/test_socket.py", line 1707, in testInterruptedTimeout
    foo = self.serv.accept()
Alarm

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "Lib/test/test_socket.py", line 1721, in testInterruptedTimeout
    self.fail("got Alarm in wrong place")
AssertionError: got Alarm in wrong place
======================================================================

Thanks a lot,

Remi.
msg143565 - (view) Author: Remi Pointel (rpointel) * Date: 2011-09-05 21:39
I add bt output with gdb 7, to have more informations.
msg143572 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-09-05 22:25
I hope that this issue is not related to threads+signals. We got many threads+signals issues on FreeBSD 6.
msg143578 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-09-06 00:12
Issue #12903 is similar to this one.
msg143586 - (view) Author: Charles-François Natali (neologix) * (Python committer) Date: 2011-09-06 07:09
> I hope that this issue is not related to threads+signals. We got many 
> threads+signals issues on FreeBSD 6.

Yep.
OpenBSD has a really specific pthread implementation (in user-space, using non-blocking I/O), so it might very well be "yet another threads+signals occurrence".

@Rémi
What happens if you run a code equivalent to test_sendall_interrupted on its own? I mean, if you try something like this:

"""
import signal, socket
c, s = socket.socketpair()
signal.signal(signal.SIGALRM, lambda x,y: 0)
signal.alarm(1)
c.sendall(b"x" * (1024**2))
"""

If it works, you could try creating a dummy thread before setting up the signal handler, something like:
"""
t = threading.Thread(target=lambda: 0)
t.start()
t.join()
"""

And retry.
The problem with all those interruption tests (like issue #12903) is that they'll break on many *BSD if another thread is running. Although in this specific case, I suspect that there are no threads running, and we're really encountering a kernel/libc bug (Victor, remember the "funny" bug on FreeBSD where kill(getpid(), <signal>) didn't deliver the signal synchronously after the first thread had been created?).
msg143640 - (view) Author: Remi Pointel (rpointel) * Date: 2011-09-06 18:01
> What happens if you run a code equivalent to test_sendall_interrupted on its own? I mean, if you try something like this:

Hi, it blocks too:

$ gdb -args ./python
[...]
(gdb) run
Starting program: /usr/ports/pobj/Python-3.2.2/Python-3.2.2/python 
Python 3.2.2 (default, Sep  5 2011, 21:21:34) 
[GCC 4.2.1 20070719 ] on openbsd5
Type "help", "copyright", "credits" or "license" for more information.
>>> import signal, socket
>>> c, s = socket.socketpair()
>>> signal.signal(signal.SIGALRM, lambda x,y: 0)
0
>>> signal.alarm(1)
0
>>> [New process 28830]
c.sendall(b"x" * (1024**2))
^C
Program received signal SIGINT, Interrupt.
Cannot access memory at address 0x98
(gdb) bt
#0  0x000000020125678a in poll () from /usr/lib/libc.so.60.1
#1  0x000000020619b4aa in _thread_kern_poll (wait_reqd=<value optimized out>)
    at /usr/src/lib/libpthread/uthread/uthread_kern.c:780
#2  0x000000020619c3a8 in _thread_kern_sched (scp=0x0)
    at /usr/src/lib/libpthread/uthread/uthread_kern.c:382
#3  0x0000000206190ade in sendto (fd=9, msg=0x2032d6020, len=1044480, flags=0, to=0x0, to_len=0)
    at /usr/src/lib/libpthread/uthread/uthread_sendto.c:63
#4  0x00000002105f670a in sock_sendall ()
   from /usr/ports/pobj/Python-3.2.2/Python-3.2.2/build/lib.openbsd-5.0-amd64-3.2/_socket.so
#5  0x000000020668b172 in PyEval_EvalFrameEx () from /usr/local/lib/libpython3.2m.so.1.0
#6  0x000000020668bf66 in PyEval_EvalCodeEx () from /usr/local/lib/libpython3.2m.so.1.0
#7  0x000000020668c22b in PyEval_EvalCode () from /usr/local/lib/libpython3.2m.so.1.0
#8  0x00000002066a93d7 in run_mod () from /usr/local/lib/libpython3.2m.so.1.0
#9  0x00000002066abcae in PyRun_InteractiveOneFlags () from /usr/local/lib/libpython3.2m.so.1.0
#10 0x00000002066abf3e in PyRun_InteractiveLoopFlags () from /usr/local/lib/libpython3.2m.so.1.0
#11 0x00000002066ac04c in PyRun_AnyFileExFlags () from /usr/local/lib/libpython3.2m.so.1.0
#12 0x00000002066bc9f4 in Py_Main () from /usr/local/lib/libpython3.2m.so.1.0
#13 0x0000000000400e75 in main ()

Thanks for your help,

Remi.
msg143642 - (view) Author: Charles-François Natali (neologix) * (Python committer) Date: 2011-09-06 18:33
> Hi, it blocks too:

Oops, I just realized there was a typo in the sample test.
The signal handler should be
lambda x,y: 1/0

and not

lambda x,y: 0
msg143648 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-09-06 20:18
I tried the following script on OpenBSD 5 with Python 3.3:
-----------                                                                                                          
import signal
import sys

s = signal.SIGALRM
signal.signal(s, lambda x,y: 1/0)
signal.alarm(1)
signal.siginterrupt(s, True)
sys.stdin.read()
-----------

The C signal handler is called, but the system call (read in this case) is not interrupted.
msg143650 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-09-06 20:58
> I tried the following script on OpenBSD 5 with Python 3.3: ...

Bad news: the script doesn't hang if Python is build without threads.

Short C program to test interrupted syscalls:
-------------                                                                                                    
#include <signal.h>
#include <stdio.h>
#include <pthread.h>

void
handler(int signum)
{
printf("HANDLER!\n");
}

void _noop()
{
}

int main()
{
int s = SIGALRM;
char buffer[1024];
int n;
static int dummy = 0;

pthread_t thread1;
pthread_create(&thread1, NULL, (void *) _noop, &dummy);
pthread_join(thread1, NULL);


signal(s, handler);
siginterrupt(s, 1);
alarm(1);
printf("read...\n");
n = read(0, buffer, 1024);
printf("read->%i\n", n);
return 0;
}
-------------

read() is interrupted after 1 second, it works.
msg143651 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-09-06 21:06
Oh, siginterrupt(SIGALRM, 0) doesn't work in a program linked to pthread. Example:
--------
#include <signal.h>
#include <stdio.h>

void
handler(int signum)
{ printf("HANDLER!\n"); }

int main()
{
int s = SIGALRM;
char buffer[1024];
int n;

signal(s, handler);
siginterrupt(s, 0);
alarm(1);
printf("read...\n");
n = read(0, buffer, 1024);
printf("read->%i\n", n);
return 0;
}
--------
This program ends after 1 second with "read->-1" if it is linked to pthread (bug!), it hangs if it is not linked to pthread (ok).
msg143652 - (view) Author: Charles-François Natali (neologix) * (Python committer) Date: 2011-09-06 21:19
> The C signal handler is called, but the system call (read in this case)
> is not interrupted.

That's what I thought...

> Bad news: the script doesn't hang if Python is build without threads.

Makes sense. When linked with pthread, all I/O syscalls are actually non-blocking.

> read() is interrupted after 1 second, it works.

Hmmm...
Does it still work if you don't a create thread beforehand?

Also, one difference is that Python uses sigaction to setup the signal handler. There might be subtle semantics change/bugs between signal/sigaction.

> Oh, siginterrupt(SIGALRM, 0) doesn't work in a program linked to
> pthread.

You could try with sigaction/SA_RESTART.

But OpenBSD's pthread implementation has severe limitations/bugs.
msg143653 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-09-06 21:46
> > read() is interrupted after 1 second, it works.
> Does it still work if you don't a create thread beforehand?

Yes, the read() is also interrupted as expected if no thread is created.

> one difference is that Python uses sigaction to setup the signal handler

If the handler is installed using the following code, read() is interrupted:
----------
sigemptyset(&sa.sa_mask);
sa.sa_handler = handler;
sa.sa_flags = 0;
sigaction(SIGALRM, &sa, NULL);
----------

Using sa.sa_flags=SA_RESTART, read() hangs (it is not interrupted). Python uses sigaction with flags=0.

> You could try with sigaction/SA_RESTART.

Using SA_RESTART, read() is not interrupted. But if the program is linked to pthread, read() is always interrupted: with sa_flags=0 or sa_flags=SA_RESTART.

> But OpenBSD's pthread implementation has severe limitations/bugs.

rthread doc contains:

"Future work:

Quite simply, signal handling is one the most complicated aspects of threads to get right. (...)"

http://www.openbsd.org/papers/eurobsd2005/tedu-rthreads.pdf
msg143699 - (view) Author: Charles-François Natali (neologix) * (Python committer) Date: 2011-09-07 18:34
> Using SA_RESTART, read() is not interrupted. But if the program is linked to pthread, read() is always interrupted: with sa_flags=0 or sa_flags=SA_RESTART.
>

Ouch...

>> But OpenBSD's pthread implementation has severe limitations/bugs.
>
> rthread doc contains:
>
> "Future work:
>
> Quite simply, signal handling is one the most complicated aspects of threads to get right. (...)"
>

This paper dates back to 2005, I was hoping they would have solved
this by now...

As for the original problem, IIUC you don't reproduce it with your C
test code...
It might be due to a subtle difference in the way Python is built
(like POSIX_SOURCE...), but it's hard to tell...
msg143744 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2011-09-08 23:25
It looks like Python cannot do much to workaround OpenBSD issues. IMO the best fix is just to skip these tests on OpenBSD, until OpenBSD handles correctly signals in programs linked to pthread. The same "fix" can be used for #12903.
msg143755 - (view) Author: Charles-François Natali (neologix) * (Python committer) Date: 2011-09-09 06:46
> It looks like Python cannot do much to workaround OpenBSD issues. IMO the best fix is just to skip these tests on OpenBSD, until OpenBSD handles correctly signals in programs linked to pthread. The same "fix" can be used for #12903.

Agreed.
msg146611 - (view) Author: Charles-François Natali (neologix) * (Python committer) Date: 2011-10-29 15:52
Rémi, do you want to submit a patch to skip those tests on OpenBSD?
msg154535 - (view) Author: Remi Pointel (rpointel) * Date: 2012-02-28 07:13
I think we could close this bug because it's du to the pthread library on OpenBSD and not Python.
We are switching to rthreads and I can't reproduce this bug.

Thanks for your help and sorry for the delay.
msg154537 - (view) Author: Charles-François Natali (neologix) * (Python committer) Date: 2012-02-28 07:36
> I think we could close this bug because it's du to the pthread library 
> on OpenBSD and not Python.

Indeed.
History
Date User Action Args
2012-02-28 08:20:31neologixsetstatus: open -> closed
2012-02-28 07:36:53neologixsettype: behavior
resolution: not a bug
messages: + msg154537
stage: resolved
2012-02-28 07:13:12rpointelsetmessages: + msg154535
2011-10-29 15:52:04neologixsetmessages: + msg146611
2011-09-09 06:46:04neologixsetmessages: + msg143755
2011-09-08 23:25:13vstinnersetmessages: + msg143744
2011-09-07 18:34:09neologixsetmessages: + msg143699
2011-09-06 21:46:16vstinnersetmessages: + msg143653
2011-09-06 21:19:36neologixsetmessages: + msg143652
2011-09-06 21:06:42vstinnersetmessages: + msg143651
2011-09-06 20:58:03vstinnersetmessages: + msg143650
2011-09-06 20:18:22vstinnersetmessages: + msg143648
2011-09-06 18:33:54neologixsetmessages: + msg143642
2011-09-06 18:01:02rpointelsetmessages: + msg143640
2011-09-06 07:09:57neologixsetmessages: + msg143586
2011-09-06 00:12:28vstinnersetmessages: + msg143578
2011-09-05 22:25:30vstinnersetmessages: + msg143572
2011-09-05 22:22:00pitrousetnosy: + vstinner, neologix
2011-09-05 21:39:38rpointelsetfiles: + OpenBSD_test_socket_gdb.log

messages: + msg143565
2011-09-05 21:33:32rpointelcreate