Hi, I wrote a simple pkcs12 demo(under Windows), it just read from a PKCS12 file and got private key and certificate. If I use single thread, it works fine. If I use multi-thread, it works fine for a while ,then popups an error dialogue "heap is corrupt".If I debug it in Visual Studio,it points to PKCS12_parse() . If I use EnterCriticalSection and LeaveCriticalSection with multi-thread, it works fine too, but as you know, the effect is as same as single thread does.
So I want to know , what shared resource is protected by CriticalSection? Is PKCS12_parse() not thread-safe? Can it be executed in multi-threads without mutex? Thank you in advance. Here is the source code. =========================================== #include <stdio.h> #include <stdlib.h> #include <string.h> #include <io.h> #include <windows.h> #include <fcntl.h> #include <sys/stat.h> #include <openssl/pkcs12.h> char p12file[256]="C:/test/ABCD.p12"; char p12pswd[10]="123456"; unsigned char *p12buf = NULL; int p12buflen = 0; #define N 30 // amount of threads #define M 20 // amount of executions per thread /* read the content from a PKCS12 file */ int Load_File(char * filename, unsigned char *pbuf, int * plen) { int fd = -1; struct stat stat_buf; int len=0,count=0,size=0; if ((fd = open(filename, O_RDONLY|O_BINARY, S_IREAD)) < 0) { return 1; } if (stat(filename, &stat_buf) != 0) { close(fd); return 1; } len = stat_buf.st_size; if (pbuf == NULL) { *plen = len; } else { count=0; while (count < len) { size = read(fd, pbuf + count, len - count); if (size <= 0) { close(fd); if (pbuf != NULL) free(pbuf); return 1; } count += size; } *plen = len; } close(fd); return 0; } int pkcs12test(unsigned char *p12buf, int p12buflen, unsigned char *p12pswd) { PKCS12 *p12; X509 *cert; EVP_PKEY *prvkey; int len; char buf[4096]; int i=0; char desc[1000]; OpenSSL_add_all_algorithms(); if ((p12buf==NULL)||(p12buflen<=0)) { printf("parameter error\n"); return -1; } p12 = d2i_PKCS12(NULL,(const unsigned char **)&p12buf,p12buflen); if(p12 == NULL) { printf("d2i_PKCS12 error\n"); return -1; } if(PKCS12_parse(p12,p12pswd,&prvkey,&cert,NULL)!=1) { if (p12!=NULL) { PKCS12_free(p12); p12=NULL; } printf("PKCS12_parse error\n"); return -1; } PKCS12_free(p12); p12=NULL; return 0; } typedef struct _param{ int threadidx; int type; } THREADPARAM; DWORD WINAPI ThreadProc( LPVOID param ) { THREADPARAM *pa; int i = 0; int ret = 0; pa = (THREADPARAM *)param; printf("[%d]thread BEGIN\n",pa->threadidx); for (i=0;i<M;i++) { ret = pkcs12test(p12buf,p12buflen,p12pswd); if (ret == 0) { printf("pkcs12test success[%d_%d]\n",pa->threadidx,i); } else { printf("pkcs12test error[%d_%d]\n",pa->threadidx,i); } } printf("[%d]thread END\n",pa->threadidx); _sleep(10*1000); return 0; } void main() { DWORD dwThreadId[N]; HANDLE hThread[N]; THREADPARAM *param[N]; int ret = 0; int i=0,j=0; ret = Load_File(p12file, NULL, &p12buflen); if (ret != 0) { return ; } p12buf = (unsigned char *)malloc(p12buflen+1); if (p12buf == NULL) { printf("malloc(%d) fail\n",p12buflen); return ; } ret = Load_File(p12file, p12buf, &p12buflen); if (ret != 0) { return ; } for( i=0; i<N; i++ ) { param[i] = (THREADPARAM *)malloc(sizeof(THREADPARAM)); if (param[i] == NULL) { printf("malloc fail\n"); return ; } param[i]->threadidx = i; param[i]->type = 1; hThread[i] = CreateThread( NULL, 0, ThreadProc, param[i], 0, &dwThreadId[i]); if (hThread[i] == NULL) { ExitProcess(i); } } printf("before wait..."); WaitForMultipleObjects(N, hThread, TRUE, INFINITE); printf("...end wait\n"); _sleep(5*60*1000); for(i=0; i<N; i++) { CloseHandle(hThread[i]); if (param[i]!=NULL) { free(param[i]); param[i]=NULL; } } return ; }